- 更简单更精准的控制显示位置,通过Gravity和offset来控制您的PopupWindow
- 本库为抽象类,对子类几乎没有约束,您完全可以像定制Activity一样来定制您的PopupWindow
- 支持Animation、Animator,随意控制您的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
}像您平时定制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>
public class DemoPopup extends BasePopupWindow { public DemoPopup(Context context) { super(context); } @Override public View onCreateContentView() { return null; } }
强烈建议在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); } }
展示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支持链式调用生成一个基于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) |
|---|---|
请看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
- 【Candy】2.2.0-alpha4(2019年04月17日)
-
【Release】2.1.9(2019年03月07日)
-
【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日)
- fixed #152
- 【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
- 【Candy】2.1.9-prerelease(2019年03月07日)
-
【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 |
| 微信 | 支付宝 |
|---|---|
因为目前还有朋友圈项目,建立了一个交流群,出于懒得管理那么多,所以如果有想法或者优化建议或者其他问题,欢迎加入"朋友圈交流群"
更多常见问题请看WIKI#常见问题
A:调用setBackgroundColor(Color.TRANSPARENT)或者setBackground(0)
A:调用dismiss(false)或者dismissWithOutAnimate()
A:设置setAllowDismissWhenTouchOutside(false)
A:PopupWindow需要windowToken,因此ApplicationContext或者Service里面是无法弹出的,建议通过发出事件通知栈顶Activity来弹出
ISSUE REF:#140
Google Issue Tracker:#36984016
A:PopupWindow内的View是无法获取WindowToken的,而粘贴功能也是一个PopupWindow,它的显示必定需要WindowToken,因此无法粘贴。
A:设置setPopupWindowFullScreen(false)
A:设置setBackPressEnable(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)。
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底部已经突破屏幕底部,无法完整显示。**