Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

亲,还在为PopupWindow烦恼吗?不如试试BasePopup,你会爱上他的~

License

Notifications You must be signed in to change notification settings

wspisces/BasePopup

Repository files navigation

1.x版本 | 2.x版本 | English

Logo图片似乎加载不出来

BasePopup - Android下打造通用便捷的PopupWindow

Release Candy License Api Author



apk体验下载

导航



特性

  • 更简单更精准的控制显示位置,通过Gravityoffset来控制您的PopupWindow
  • 本库为抽象类,对子类几乎没有约束,您完全可以像定制Activity一样来定制您的PopupWindow
  • 支持AnimationAnimator,随意控制您的PopupWindow的动画,再也不用去写蛋疼的xml了
  • 背景变暗、背景换色甚至背景给个Drawable都是一句话的事情
  • 背景模糊亦或是局部模糊也仅仅需要您一句话的配置
  • 返回键控制点击外部Dismiss控制,外部事件响应控制三者分离,再也不用担心我的PopupWindow各种按键响应问题
    • 如果不满足默认的事件,没问题,我们还提供了事件传递,您的事件您来把握
  • PopupWindow跟随AnchorView位置不准?屏幕外不消失?在这里,Link方法为您排忧解难
  • 支持链式调用,还在为简单的PopupWindow使用不得不继承库的抽象类而感到烦躁?不妨来试试QuickPopupBuilder,想必您会爱上它的


注意事项

WARN:

  • 请务必仔细阅读本README,每个版本升级请务必查阅更新日志,这可以为您减少不必要弯路
  • 请注意引用版本的问题,Release版本是稳定版,Candy是预览版。
    • Release版本:一般在Candy版本反复验证修复后发布到Release,如果您对稳定性要求较高,请使用Release版本。
    • Candy版本:一般新功能、issue修复都会发布到Candy版本,Candy版本发布比较频繁,但通常会拥有新的功能,如果您喜欢试验新功能同时对稳定性要求不高,请使用Candy版本。
    • Release和Candy两个版本互相切换可能会导致Build失败,这时候您Clean一下Project即可
  • 如果您是以前1.x版本的用户,现在想更新到2.x,请在更新前查阅:1.x迁移到2.x帮助文档

Android P已经适配,感谢@Guolei1130收集的方法。

文章地址:android_p_no_sdkapi_support

本库一开始采用360的方法,但不得不走Native,为了个Popup不得不引入so感觉很不值得,在看到这篇文章后,才想起UnSafe类,因此本库采用方法5。

如果以后UnSafe类移除掉的话,再考虑Native方法。

最后再一次感谢大牛提供的方法~



声明:

BasePopup并非一个 "一句话完成需求" 的库,从起名带有 【Base】 也应该可以知道这是一个高度抽象的类。
这也意味着本库所提供的api并不能具体到某个需求,因此,具体的需求比如点击事件,比如列表弹窗等等都需要您自行完成。
因为众口难调,你的需求并不适用于别人的需求,而作为一个通用库,就如ListAdapter一样,最大程度的开放给用户完成是最好的方案。
因此,如果您期望使用BasePopup可以一句话完成所有事情,很抱歉~可能本库不能满足您的需求。



快速入门


更多使用方法请查看Wiki#使用方法

依赖

Release Candy
Download Download

添加依赖到Gradle(请把{$latestVersion}替换成上面的Jcenter标签所示版本)

	dependencies {
	 implementation 'com.github.razerdp:BasePopup:{$latestVersion}'
	 
	 //candy版本
	 //implementation 'com.github.razerdp:BasePopup_Candy:{$latestVersion}'
	}

配置

模糊配置

从1.9.0-alpha开始支持背景模糊(只需要一个方法:setBlurBackgroundEnable(boolean))

RenderScript最低支持api 17(更低的情况将会使用fastblur),您需要在gradle配置一下代码

defaultConfig {
 renderscriptTargetApi 25
 renderscriptSupportModeEnabled true
 }

普通使用

1.编写您的xml文件

像您平时定制View布局文件一样定制您的PopupWindow布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:layout_gravity="center"
 android:background="@android:color/holo_blue_dark"
 android:orientation="vertical"
 >
 <TextView
 android:id="@+id/tx_1"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:gravity="center"
 android:padding="16dp"
 android:text="test1"
 android:textColor="@color/color_black1"/>
</LinearLayout>

2.创建您的Popup类并继承BasePopupWindow

public class DemoPopup extends BasePopupWindow {
 public DemoPopup(Context context) {
 super(context);
 }
 @Override
 public View onCreateContentView() {
 return null;
 }
}

3.补充对应方法

强烈建议在onCreateContentView()里使用createPopupById()来进行inflate,这样本库才能正确的做出对应的解析和适配

public class DemoPopup extends BasePopupWindow {
 public DemoPopup(Context context) {
 super(context);
 }
 // 必须实现,这里返回您的contentView
 // 为了让库更加准确的做出适配,强烈建议使用createPopupById()进行inflate
 @Override
 public View onCreateContentView() {
 return createPopupById(R.layout.popup_normal);
 }
 
 // 以下为可选代码(非必须实现)
 // 返回作用于PopupWindow的show和dismiss动画,本库提供了默认的几款动画,这里可以自由实现
 @Override
 protected Animation onCreateShowAnimation() {
 return getDefaultScaleAnimation(true);
 }
 @Override
 protected Animation onCreateDismissAnimation() {
 return getDefaultScaleAnimation(false);
 }
}

4.show!

展示PopupWindow的方法有三种,分别是showPopupWindow()showPopupWindow(View anchor)showPopupWindow(int x, int y):

new DemoPopup(getContext()).showPopupWindow();
//new DemoPopup(getContext()).showPopupWindow(v);
//new DemoPopup(getContext()).showPopupWindow(x,y);

这三个方法有不同的含义:

  • showPopupWindow():无参传入,此时PopupWindow参考对象为屏幕(或者说整个DecorView),Gravity的表现就像在FrameLayout里面的Gravity表现一样,表示其处于屏幕的哪个方位
  • showPopupWindow(View anchor):传入AnchorView,此时PopupWindow参考对象为传入的anchorView,Gravity的表现则意味着这个PopupWindow应该处于目标AnchorView的哪个方位
  • showPopupWindow(int x, int y):传入位置信息,此时PopupWindow将会在指定位置弹出。

建议:如果PopupWindow需要重复展示或者保留状态,建议作为成员变量使用,而不要作为局部变量每次都创建

关于Gravity的更多api,请查看:Wiki-Api:Gravity

例子展示:

  • showPopupWindow()无参传入
gravity = CENTER
上述例子中xml写明了layout_gravity=center
gravity = RIGHT | CENTER_VERTICAL

  • showPopupWindow(View v)传入anchorView
gravity = CENTER
上述例子中xml写明了layout_gravity=center
gravity = RIGHT | CENTER_VERTICAL

  • showPopupWindow(int x, int y)传入位置x,y坐标
gravity = CENTER
上述例子中xml写明了layout_gravity=center


QuickPopupBuilder链式调用

QuickPopupBuilder支持链式调用生成一个基于QuickPopup的PopupWindow,该Builder旨在快速建立一个简单的不包含复杂逻辑的PopupWindow,如上述案例,避免过于简单的PopupWindow也要继承BasePopupWindow,导致存在过多的类。

示例代码


如果您并不需要很详细的定义一个PopupWindow,您也可以选择QuickPopupBuilder采取链式写法快速编写出一个Popup以使用。

注意:默认QuickPopupBuilder.QuickPopupConfig配置中PopupWindow动画为缩放弹出和消失

 QuickPopupBuilder.with(getContext())
 .contentView(R.layout.popup_normal)
 .config(new QuickPopupConfig()
 .gravity(Gravity.RIGHT | Gravity.CENTER_VERTICAL)
 .withClick(R.id.tx_1, new View.OnClickListener() {
 @Override
 public void onClick(View v) {
 Toast.makeText(getContext(), "clicked", Toast.LENGTH_LONG).show();
 }
 }))
 .show();
		//.show(anchorView);
show() show(anchorView)


Api(请看Wiki)

请看wiki(陆续完善中)

Link👉WIKI


更新日志 (历史更新)

  • 【Candy】2.2.0

    • 【Candy】2.2.0-alpha4(2019年04月17日)
      • fixed #164
      • 优化测量逻辑,尝试修复wrap_content等高度问题
    • 【Candy】2.2.0-alpha2(2019年03月21日)
      • 增加setMaxWidth()setMaxHeight()方法,想最大半屏显示?走起~
    • 【Candy】2.2.0-alpha(2019年03月21日)
      • 增加setBackgroundView(View)方法,现在BasePopup的背景控件可以随意由你定制啦~当然PopupWindow的背景动画控制方法依旧生效
    • 【other】
      • add 996 license
  • 【Release】2.1.9(2019年03月07日)

    • 优化对android P刘海的支持,允许PopupWindow布局到刘海,fixed #154
    • 修复Quickpopup没有设置回调的问题
    • OnDismissListener添加退出动画开始的回调
    • 优化模糊逻辑
    • 优化退出动画逻辑
    • fixed #152
    • 优化代码,修复覆盖动画监听器的bug,优化layout逻辑
    • 为模糊图片方法添加oom捕捉
    • 优化背景和局部模糊逻辑
    • 去除lib的AndroidManifest内容,预防冲突,fixed #149
    • 针对DialogFragment适配,fixed #145
  • 【Candy】2.1.9

    • 【Candy】2.1.9-prerelease(2019年03月07日)
      • 优化对android P刘海的支持,允许PopupWindow布局到刘海,fixed #154
    • 【Candy】2.1.9-beta4~5(2019年03月1日)
      • 修复quickpopup没有设置回调的问题
      • OnDismissListener添加退出动画开始的回调
      • 优化模糊逻辑
      • 优化退出动画逻辑
    • 【Candy】2.1.9-beta3(2019年03月1日)
    • 【Candy】2.1.9-beta1(2019年02月28日)
      • 优化代码,修复覆盖动画监听器的bug,优化layout逻辑
    • 【Candy】2.1.9-beta(2019年2月26日)
      • 为模糊图片方法添加oom捕捉
    • 【Candy】2.1.9-alpha4(2019年2月21日)
      • 优化背景和局部模糊逻辑
    • 【Candy】2.1.9-alpha3(2019年2月21日)
      • 紧急修复alpha2留下的坑
    • 【Candy】2.1.9-alpha2(2019年2月19日)
      • 去除lib的AndroidManifest内容,预防冲突,fixed #149
    • 【Candy】2.1.9-alpha1(2019年02月18日)
      • 针对DialogFragment适配,fixed #145
  • 【Release】2.1.8(2019年01月26日)

    • 本次版本更新添加了许多新特性哦~特别是不拦截事件的背景黑科技又回来了
    • 更新细节:
      • 适配使用了ImmersionBar的情况
      • 修复对横屏不兼容的问题
      • 修复构造器传入宽高无效的问题
      • 支持不拦截事件下的背景蒙层,没错!那个黑科技换了个更友好的方式来啦~
      • 修复popup弹出的时候,金刚键(虚拟按键)一同弹出的问题(锁屏回来导致焦点变化从而导致全屏Activity又出现虚拟导航栏这个不算哈)
      • QuickPopupConfig增加dismissOnOutSideTouch()方法
      • 优化QuickPopupBuilder,增加Wiki
      • 针对#138出现的问题进行优化
      • 修复setAlignBackgroundGravity()setAlignBackground()互相覆盖导致的顺序硬性要求问题

例子预览

GravityPopupFrag LocatePopupFrag
AnyPosPopupFrag UpdatePopupFrag
BlurSlideFromBottomPopupFrag CommentPopup
SlideFromBottomPopup InputPopup
ListPopup MenuPopup

打赏(看在我那么努力维护的份上。。。给个零食呗~)

微信 支付宝

交流群:590777418

因为目前还有朋友圈项目,建立了一个交流群,出于懒得管理那么多,所以如果有想法或者优化建议或者其他问题,欢迎加入"朋友圈交流群"


常见问题

更多常见问题请看WIKI#常见问题

Q:如何取消默认的背景颜色

A:调用setBackgroundColor(Color.TRANSPARENT)或者setBackground(0)




Q:如何在dismiss()时不执行退出动画

A:调用dismiss(false)或者dismissWithOutAnimate()




Q:点击popupwindow背景部分不想让popupwindow隐藏怎么办

A:设置setAllowDismissWhenTouchOutside(false)




Q:Service里无法弹出

A:PopupWindow需要windowToken,因此ApplicationContext或者Service里面是无法弹出的,建议通过发出事件通知栈顶Activity来弹出




Q:为什么PopupWindow里面的EditText无法粘贴

ISSUE REF:#140

Google Issue Tracker:#36984016

A:PopupWindow内的View是无法获取WindowToken的,而粘贴功能也是一个PopupWindow,它的显示必定需要WindowToken,因此无法粘贴。




Q:如何不让PopupWindow的蒙层覆盖状态栏

A:设置setPopupWindowFullScreen(false)




Q:如何点击back键不关闭pop

A:设置setBackPressEnable(false)




Q:为什么设置setAllowInterceptTouchEvent(false)后,蒙层或者背景模糊都消失了

A:(削除) 在2.0.0到2.0.9之间,setAllowInterceptTouchEvent()不影响蒙层或背景,但从2.1.0开始,不再开启这个黑科技,而是选择跟官方保持同步,原因在于如果背景模糊或者有蒙层,那么该PopupWindow理应拦截事件,而不应该穿透事件,否则不应该拥有背景蒙层。

(削除ここまで)
但是!从2.1.8-beta6之后,该黑科技又支持啦~换了个比较友好的方式

同时,因为系统PopupWindow默认是clipToScreen,也就是限制PopupWindow在屏幕内显示,当view边缘超过屏幕的时候,PopupWindow会反向移动以完整展示内容,因此如果您的PopupWindow需要突破屏幕显示(比如高度是全屏,但展示在某个view下面,此时bottom大于屏幕底部),请设置setClipToScreen(false)




Q:根布局高度match_parentwrap_content的区别

A:当根布局是match_parent的时候,basepopup会做一定的差异处理。
当您设置了setClipToScreen(true)时,如果您的根布局是match_parent,那么意味着您的布局最大高度仅为屏幕高度,如果您的根布局是wrap_content,那么最大高度可能是可以突破屏幕高度的。
例如demo中的全屏listview

<RelativeLayout
 xmlns:android="http://schemas.android.com/apk/res/android"
 android:layout_width="match_parent"
 android:layout_height="match_parent" // 请留意这里
 android:background="@android:color/white"
 >
 <ListView
 android:id="@+id/popup_list"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:divider="@color/line_bg"
 android:dividerHeight="0.5dp"
 android:scrollbars="vertical"
 />
</RelativeLayout>
layout_height = match_parent layout_height = wrap_content


**留意两张图的listview底部区别,其中wrap_content底部已经突破屏幕底部,无法完整显示。**


License

Apache-2.0

About

亲,还在为PopupWindow烦恼吗?不如试试BasePopup,你会爱上他的~

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Java 100.0%

AltStyle によって変換されたページ (->オリジナル) /