1.x版本 | 2.x版本
- 更简单更精准的控制显示位置,通过Gravity和offset来控制您的PopupWindow
- 本库为抽象类,对子类几乎没有约束,您完全可以像定制Activity一样来定制您的PopupWindow
- 支持Animation、Animator,随意控制您的PopupWindow的动画,再也不用去写蛋疼的xml了
- 背景变暗、背景换色甚至背景给个Drawable都是一句话的事情
- 背景模糊亦或是模糊背景某个具体的View也仅仅需要您一句话的配置
- 返回键、点击外部是否Dismiss,外部是否可以响应事情三者分离,再也不用担心我的PopupWindow各种按键响应问题
- 如果不满足默认的事件,没问题,我们还提供了事件传递,您的事件您来把握
- 系统的坑?不,我们来把控,通过hook掉系统的windowmanager来由我们把握PopupWindow的各种事情,防止不同版本出现的各种适配问题
- 支持链式调用,还在为简单的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方法。
最后再一次感谢大牛提供的方法~
Release | Candy |
---|---|
添加依赖到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)
:
new DemoPopup(getContext()).showPopupWindow();
//new DemoPopup(getContext()).showPopupWindow(v);
这两个方法有不同的含义:
showPopupWindow()
:无参传入,此时PopupWindow参考对象为屏幕(或者说整个DecorView),Gravity的表现就像在FrameLayout里面的Gravity表现一样,表示其处于屏幕的哪个方位showPopupWindow(View anchor)
:传入AnchorView,此时PopupWindow参考对象为传入的anchorView,Gravity的表现则意味着这个PopupWindow应该处于目标AnchorView的哪个方位
建议:如果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 |
---|---|
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.1.0-betaX(2018/12)
- 针对2.x的重构,撒花~
- 本次更新内容:
- 去掉每次都add两次View的骚操作,合并成同一个PopupWindow,所以Layout Inspector不再让人迷惑为啥有两个PopupWindow了
- 增加Gravity的支持,再也不用蛋疼的去计算蛋疼的offset了,而且布局文件真的可以wrap_content了
- 接管layout过程,所以各个版本的PopupWindow都不一样?不存在滴。。。同时autoLocate支持RecyclerView啦~
- 增加对contentView的xml的解析(前提是使用createPopupById方法),再也不怕被强制设置宽高了
- fullScreen支持输入法布局适配!心塞了好久的问题终于解决
- 增加对5.1和5.1.1官方两个PopupWindow重叠后在切换时层次变化的bug的适配
- 优化代码,去除冗余代码
- README大翻新
-
【Release】2.0.8.1(2018/10/29)
-
【Release】2.0.8(2018/10/29)
- fixed #93
- 修复部分崩溃问题,发布release
-
【Candy】2.0.8-alpha3(2018/10/25)
-
【Candy】2.0.8-alpha2(2018/10/19)
- 修复QuickPopupBuilder的click事件无响应问题,增加background方法
- 修复设置background(0)时无法找到资源而崩溃的问题
对应popup | 预览 |
---|---|
LocatePopupFrag.java | ![]() |
BlurSlideFromBottomPopup.java | ![]() |
CommentPopup.java | ![]() |
ScalePopup.java | ![]() |
SlideFromBottomPopup.java | ![]() |
InputPopup.java | ![]() |
ListPopup.java | ![]() |
MenuPopup.java | ![]() |
微信 | 支付宝 |
---|---|
![]() |
![]() |
因为目前还有朋友圈项目,建立了一个交流群,出于懒得管理那么多,所以如果有想法或者优化建议或者其他问题,欢迎加入“朋友圈交流群”
A:调用setBackgroundColor(Color.TRANSPARENT)或者setBackground(0)
A:调用dismiss(false)或者dismissWithOutAnimate()
A:设置setAllowDismissWhenTouchOutside(false)
A:PopupWindow需要windowToken,因此ApplicationContext或者Service里面是无法弹出的,建议通过发出事件通知栈顶Activity来弹出
A:设置setPopupWindowFullScreen(false)
A:设置setBackPressEnable(false)
A:在2.0.0到2.0.9之间,setAllowInterceptTouchEvent()不影响蒙层或背景,但从2.1.0开始,不再开启这个黑科技,而是选择跟官方保持同步,原因在于如果背景模糊或者有蒙层,那么该PopupWindow理应拦截事件,而不应该穿透事件,否则不应该拥有背景蒙层。