前言
断断续续地,利用工作之余的不少时间归纳整合了这个XPopUp。虽然没啥高深的技术,但是我认为这个库能给大家在项目上的弹框处理带来些许的方便,使用它,大家就不必频繁的新建class文件,频繁地写重复代码,直接链式调用,提供全面的api,应该能满足项目上绝大多数的业务,并且覆盖了Android所有的弹框类型(Dialog、BottomSheetDialog、DialogFragment、BottomSheetDialogFragment、PopupWindow、DialogActivity),总结起来就是调用简单、功能强大。
功能特点
- 层次结构分明,分工明确
- 采用链式调用一点到底
- 支持Android多种弹框:Dialog、BottomSheetDialog、DialogFragment、BottomSheetDialogFragment、PopupWindow、DialogActivity
- 支持设置弹窗的主题样式、宽高(最大宽高及屏幕宽高比等)、背景透明度、圆角、显示位置、显示消失动画
- 支持设置弹窗ContentView相关控件View的属性,如
- 支持设置弹窗关闭的逻辑,如返回键、点击外部空白区域
- 支持设置弹窗的显示及关闭事件监听
- 支持设置弹窗自动消失
- …
下一步计划添加弹窗的优先级队列和全局弹窗,有什么好的建议和想法也可以提出来!!
设计实现
- XPopupCompat 单例实现的XPopup管理类
- XPopup 弹窗实体,所有的弹窗类型对象都可以认为是一个XPopup,里面维护了弹窗的Config和Delegate对象
- XPopupInterface XPopup的抽象接口类
- Config 弹窗的配置对象,不同的弹窗类型有不同的Config对象,负责存储弹窗的相关属性,如DialogConfig、DialogFragmentConfig等
- Delegate 弹窗的代理对象,不同的弹窗类型有不同的Delegate对象,负责处理弹窗的相关属性,如DialogDelegate、DialogFragmentDelegate等
- XPopupRootView 弹窗的RoottView
- XPopupViewHolder 处理弹窗ContentView的Holder对象,类似RecyclerView的BaseViewHolder
项目引入该库
在你的 Project build.gradle文件中添加:
allprojects {
repositories {
...
maven { url 'https://jitpack.io' }
}
}
在你的 Module build.gradle文件中添加:
dependencies {
implementation 'com.github.HHotHeart:XPopUp:1.0.0'
}
如何使用
我们可以通过XPopupCompat asXXX系列的方法来展示不同的弹框类型,如:
- asDialog
- asBottomSheetDialog
- asDialogFragment
- asBottomSheetDialogFragment
- asPopupWindow
- asDialogActivity
下面以展示Dialog进行说明:
XPopupCompat.get().asDialog(DialogDemoActivity.this)
.themeStyle(R.style.XPopup_Dialog)
.view(R.layout.popup_test)
.radius(50)
.animStyle(R.style.PopupEnterExpandExitShrinkAnimation)
.widthInPercent(0.8f)
.cancelable(false)
.cancelableOutside(false)
.autoDismissTime(5000)
.gravity(Gravity.CENTER)
.clickListener(R.id.btn_left, (popupInterface, view, holder) -> {
popupInterface.dismiss();
Toast.makeText(
DialogDemoActivity.this,
"点击了" + ((Button) holder.getView(R.id.btn_left)).getText(),
Toast.LENGTH_SHORT)
.show();
})
.longClickIds(R.id.btn_left, R.id.btn_right)
.longClickIdsListener((popupInterface, view, holder) -> {
if (view.getId() == R.id.btn_left) {
Toast.makeText(
DialogDemoActivity.this,
"长按了" + ((Button) holder.getView(R.id.btn_left)).getText(),
Toast.LENGTH_SHORT)
.show();
} else if (view.getId() == R.id.btn_right) {
Toast.makeText(
DialogDemoActivity.this,
"长按了" + ((Button) holder.getView(R.id.btn_right)).getText(),
Toast.LENGTH_SHORT)
.show();
}
return true;
})
.dismissListener(popupInterface ->
Toast.makeText(
DialogDemoActivity.this,
"消失监听",
Toast.LENGTH_SHORT)
.show())
.showListener(popupInterface ->
Toast.makeText(
DialogDemoActivity.this,
"显示监听",
Toast.LENGTH_SHORT)
.show())
.bindViewListener((XPopupViewHolder holder) -> {
holder.setText(R.id.tv_popup_title, "XPopup");
})
.create()
.show();
如果我们需要在弹窗展示期间改变ContentView一些控件的属性,这时我们可以经过Config配置对象的create()方法获取XPopup对象实例,通过其就可以拿到ContentView的XPopupViewHolder对象,进而改变相关控件的属性,如:
XPopup<DialogConfig, DialogDelegate> xPopup = XPopupCompat.get().asDialog(DialogDemoActivity.this)
.view(R.layout.popup_test)
.gravity(Gravity.BOTTOM)
.autoDismissTime(10000)
.create();
xPopup.show();
new Handler(Looper.getMainLooper()).postDelayed(() ->
xPopup.getPopupViewHolder().setText(R.id.tv_popup_title, "获取xPopup对象,更新标题"), 5000);
框架的普通Dialog和DialogActivity默认实现的主题样式:R.style.XPopup_Dialog
<!-- 普通Dialog主题样式 -->
<style name="XPopup.Dialog" parent="Theme.MaterialComponents.DayNight.Dialog">
<item name="android:windowNoTitle">true</item>
<!-- 是否不显示title 继承AppCompat样式-->
<item name="windowNoTitle">true</item>
<!-- 设置dialog显示区域外部的背景(透明),有圆角,圆角外部区域显示这个颜色 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 设置dialog的背景(透明),此颜色值会覆盖掉windowBackground的值 -->
<item name="android:background">@android:color/transparent</item>
<item name="android:colorBackground">@android:color/transparent</item>
<!-- 设置灰度的值,为1时,除Dialog内容布局高亮其它全黑,系统的默认值是0.6 -->
<item name="android:backgroundDimAmount">0.5</item>
<!-- 是否允许背景灰暗,即是否让显示区域以外使用上面设置的黑色半透明背景,设为false时,等价于backgroundDimAmount=0 -->
<item name="android:backgroundDimEnabled">true</item>
<!-- 是否有遮盖 -->
<item name="android:windowContentOverlay">@null</item>
<!-- 设置Dialog的windowFrame框(无) -->
<item name="android:windowFrame">@null</item>
<!-- 是否浮现在activity之上,必须设为true,否则自己独立占一个界面,这根本就不像是一个对话框了 -->
<item name="android:windowIsFloating">true</item>
<!-- 是否半透明,貌似没什么卵用 -->
<item name="android:windowIsTranslucent">true</item>
</style>
BottomSheetDialog默认实现的主题样式:R.style.XPopup_BottomSheetDialog
<!-- BottomSheetDialog样式 -->
<style name="XPopup.BottomSheetDialog" parent="Theme.Design.BottomSheetDialog">
<item name="android:windowNoTitle">true</item>
<!-- 是否不显示title 继承AppCompat样式-->
<item name="windowNoTitle">true</item>
<!-- 设置dialog显示区域外部的背景(透明),有圆角,圆角外部区域显示这个颜色 -->
<item name="android:windowBackground">@android:color/transparent</item>
<!-- 设置dialog的背景(透明),此颜色值会覆盖掉windowBackground的值 -->
<item name="android:background">@android:color/transparent</item>
<item name="android:colorBackground">@android:color/transparent</item>
<!-- 设置灰度的值,为1时,除Dialog内容布局高亮其它全黑,系统的默认值是0.6 -->
<item name="android:backgroundDimAmount">0.5</item>
<!-- 是否允许背景灰暗,即是否让显示区域以外使用上面设置的黑色半透明背景,设为false时,等价于backgroundDimAmount=0 -->
<item name="android:backgroundDimEnabled">true</item>
<!-- 是否有遮盖 -->
<item name="android:windowContentOverlay">@null</item>
<!-- 设置Dialog的windowFrame框(无) -->
<item name="android:windowFrame">@null</item>
<!-- 是否浮现在activity之上,必须设为true,否则自己独立占一个界面,这根本就不像是一个对话框了 -->
<item name="android:windowIsFloating">true</item>
<!-- 是否半透明,貌似没什么卵用 -->
<item name="android:windowIsTranslucent">true</item>
</style>
DialogActivity动画设置:
<!-- 自定义DialogActivity动画 -->
<style name="ActivityEnterRightExitLeftAnimation">
<item name="android:activityOpenEnterAnimation">@anim/in_from_right</item>
<item name="android:activityOpenExitAnimation">@null</item>
<item name="android:activityCloseEnterAnimation">@null</item>
<item name="android:activityCloseExitAnimation">@anim/out_to_left</item>
</style>
其它弹窗的动画设置:
<style name="PopupEnterExpandExitShrinkAnimation">
<item name="android:windowEnterAnimation">@anim/enter_folds_expand</item>
<item name="android:windowExitAnimation">@anim/exit_folds_shrink</item>
</style>
具体的设置可参考项目demo,这里就不细说了。
XPopUp属性配置说明
基本公共属性
属性 | 设置方法 | 说明 |
---|
mContext | 构造函数BaseConfig(Context context) | 上下文 | mThemeStyle | themeStyle(@StyleRes int themeStyle) | 主题样式,PopupWindow不支持此属性 | mAnimStyle | animStyle(@StyleRes int animStyle) | 动画 | mContentView | view(View contentView) view(@LayoutRes int contentViewResId) | 内容View | mOnBindViewListener | bindViewListener(XPopupInterface.OnBindViewListener listener) | View绑定到XPopup前的监听器 | mOnShowListener | showListener(XPopupInterface.OnShowListener onShowListener) | XPopup显示监听器 | mOnDismissListener | dismissListener(XPopupInterface.OnDismissListener onDismissListener) | XPopup关闭监听器 | mClickIds | clickIds(@IdRes int… clickIds) | 点击控件id集合 | mOnClickListener | clickIdsListener(@NonNull XPopupInterface.OnClickListener onClickListener) | 控件点击事件监听器 | mLongClickIds | longClickIds(@IdRes int… longClickIds) | 长按控件id集合 | mOnLongClickListener | longClickIdsListener(@NonNull XPopupInterface.OnLongClickListener onLongClickListener) | 控件长按事件监听器 | mWidth | width(int width) matchWidth() wrapWidth() | 宽,默认ViewGroup.LayoutParams.MATCH_PARENT | mHeight | height(int height) matchHeight() wrapHeight() | 高,默认ViewGroup.LayoutParams.WRAP_CONTENT | mMaxWidth | maxWidth(int maxWidth) | 最大宽 | mMaxHeight | maxHeight(int maxHeight) | 最大高 | mWidthInPercent | widthInPercent(float widthInPercent) | 屏幕宽度比 | mHeightInPercent | heightInPercent(float heightInPercent) | 屏幕高度比 | mGravity | gravity(int gravity) | 弹窗位置,BottomSheet系列弹窗的位置恒为Gravity.BOTTOM | mBackgroundDrawable | backgroundDrawable(Drawable backgroundDrawable) | 弹窗window的背景 | mDimAmount | dimAmount(float dimAmount) | 弹窗周围的亮度 | mAutoDismissTime | autoDismissTime(long autoDismissTime) | x秒后自动消失 | mCancelable | cancelable(boolean cancelable) | 返回键事件关闭弹窗,默认true,对于PopupWindow无效,调用者自行处理其此事件 | mCancelableOutside | cancelableOutside(boolean cancelableOutside) | 点击外部区域关闭弹窗,默认true | mRadius mRadiusSideLeft mRadiusSideTop mRadiusSideRight mRadiusSideBottom | radius(int radius) radiusSideLeft(int radiusSideLeft) radiusSideTop(int radiusSideTop) radiusSideRight(int radiusSideRight) radiusSideBottom(int radiusSideBottom) | 圆角 左边圆角 上边圆角 右边圆角 下边圆角 |
这里只列举XPopUp的公共属性,至于不同的弹窗类型,其对应的Config定义了特有的属性,这里就不列举出来了,详细的属性可以去看XXXConfig系列源码。
总结
XPopUp是一个弹窗处理框架,整合了Android几乎所有的弹窗类型,主要是为了简化弹窗的处理方式,直接链式调用,发布这个初版基本能满足大多数业务场景。接下来自己也会继续完善这个库,将弹窗优先级和全局弹窗功能加进来,当然DialogActivity也可以实现不依赖Activity的全局弹窗,自己一个人的力量有限,XPopUp可能有些功能设计考虑的不是很充分,难免会有些错误,希望大家在使用中能多多提点意见,自己也会努力去改进和完善。
最后欢迎大家start!
|