功能强大,UI简洁,交互优雅的通用弹窗!可以替代Dialog,PopupWindow,PopupMenu,BottomSheet等组件,自带十几种效果良好的动画, 支持完全的UI和动画自定义!
编写本库的初衷有以下几点:
- 项目有这样常见需求:中间和底部弹出甚至可拖拽的对话框,指定位置的PopupMenu或者PopupWindow,指定区域阴影的弹出层效果
- 市面上已有的类库要么功能不足够,要么交互效果不完美,有着普遍的缺点,就像BottomSheet存在的问题一样。比如:窗体消失的动画和背景渐变动画不一致,窗体消失后半透明背景仍然停留一会儿
设计思路: 综合常见的弹窗场景,我将其分为3类:
- Center类型,就是在中间弹出的弹窗,比如确认和取消弹窗,Loading弹窗
- Bottom类型,就是从页面底部弹出,比如从底部弹出的分享窗体,知乎的从底部弹出的评论列表
- Attach类型,就是弹窗的位置需要依附于某个View,就像系统的PopupMenu效果一样,但PopupMenu的自定义性很差
尽管我已经内置了几种常见弹窗的实现,但不可能满足所有的需求,你很可能需要自定义;你自定义的弹窗类型应该属于这3种之一。
动画设计: 为了增加交互的趣味性,遵循Material Design,在设计动画的时候考虑了很多细节,过渡,层级的变化。具体可以从Demo中感受。
implementation 'com.lxj:xpopup:latest release'
为了方便使用,已经内置了几种常见弹窗的实现:
-
显示确认和取消对话框
XPopup.get(getContext()).asConfirm("我是标题", "我是内容", new OnConfirmListener() { @Override public void onConfirm() { toast("click confirm"); } }) .show();
-
显示带输入框的确认和取消对话框
XPopup.get(getContext()).asInputConfirm("我是标题", "请输入内容。", new OnInputConfirmListener() { @Override public void onConfirm(String text) { toast("input text: " + text); } }) .show();
-
显示中间弹出的列表弹窗
XPopup.get(getActivity()).asCenterList("请选择一项",new String[]{"条目1", "条目2", "条目3", "条目4"}, new OnSelectListener() { @Override public void onSelect(int position, String text) { toast("click "+text); } }) .show();
-
显示中间弹出的加载框
XPopup.get(getActivity()).asLoading().show();
-
显示从底部弹出的列表弹窗
XPopup.get(getActivity()).asBottomList("请选择一项",new String[]{"条目1", "条目2", "条目3", "条目4","条目5"}, new OnSelectListener() { @Override public void onSelect(int position, String text) { toast("click "+text); } }) .show();
-
显示依附于某个View的弹窗
XPopup.get(getActivity()).asAttachList(new String[]{"分享", "编辑", "不带icon"}, new int[]{R.mipmap.ic_launcher, R.mipmap.ic_launcher}, new OnSelectListener() { @Override public void onSelect(int position, String text) { toast("click "+text); } }) .atView(v) // 依附于所点击的View,必须设置 .show();
-
关闭弹窗
XPopup.get(getContext()).dismiss();
-
自定义弹窗
当你自定义弹窗的时候,需要选择继承
CenterPopupView
,BottomPopupView
或者AttachPopupView
三者之一。假设需要自定义Center类型的弹窗:class CustomPopup extends CenterPopupView{ public CustomPopup(@NonNull Context context) { super(context); } // 返回自定义弹窗的布局 @Override protected int getImplLayoutId() { return R.layout.custom_popup; } // 执行初始化操作,比如:findView,设置点击,或者任何你弹窗内的业务逻辑 @Override protected void initPopupContent() { super.initPopupContent(); findViewById(R.id.tv_close).setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { dismiss(); // 关闭弹窗 } }); } // 设置最大宽度,看需要而定 @Override protected int getMaxWidth() { return super.getMaxWidth(); } // 设置最大高度,看需要而定 @Override protected int getMaxHeight() { return super.getMaxHeight(); } // 设置自定义动画器,看需要而定 @Override protected PopupAnimator getPopupAnimator() { return super.getPopupAnimator(); } }
使用自定义弹窗:
XPopup.get(getContext()) .asCustom(new CustomPopup(getContext())) .show();
-
自定义动画
自定义动画已经被设计得非常简单,动画和弹窗是无关的;这意味着你可以将动画设置给内置弹窗或者自定义弹窗。继承
PopupAnimator
,实现3个方法:- 如何初始化动画
- 动画如何开始
- 动画如何结束
比如:自定义一个旋转的动画:
class RotateAnimator extends PopupAnimator{ @Override public void initAnimator() { targetView.setScaleX(0); targetView.setScaleY(0); targetView.setAlpha(0); targetView.setRotation(360); } @Override public void animateShow() { targetView.animate().rotation(0).scaleX(1).scaleY(1).alpha(1).setInterpolator(new FastOutSlowInInterpolator()).setDuration(animateDuration).start(); } @Override public void animateDismiss() { targetView.animate().rotation(360).scaleX(0).scaleY(0).alpha(0).setInterpolator(new FastOutSlowInInterpolator()).setDuration(animateDuration).start(); } }
使用自定义动画:
XPopup.get(getContext()) .asConfirm(...) .customAnimator(new RotateAnimator()) .show();
-
其他
-
设置主色调
默认情况下,XPopup的主色为灰色,这体现在Button和EditText的颜色上。因为XPopup是单例,所以主色调只需要设置一次即可,可以放在Application中设置。
XPopup.get(this).setPrimaryColor(getResources().getColor(R.color.colorPrimary));
-
其他设置
XPopup.get(this) .hasShadowBg(true) // 是否有半透明的背景,默认为true .dismissOnBackPressed(true) // 按返回键是否关闭弹窗,默认为true .dismissOnTouchOutside(true) // 点击外部是否关闭弹窗,默认为true .popupAnimation(PopupAnimation.ScaleAlphaFromCenter) // 设置内置的动画 .customAnimator(null) // 设置自定义的动画器
- Bottom类型的弹出支持手势拖拽,就像知乎的评论弹窗那样
- 手指长按弹出弹窗,就像微信的列表长按效果
- 局部阴影覆盖的弹窗,就像淘宝的商品列表筛选框那样
- DrawerLayout效果,就像从左边或右边打开的DrawerLayout那样