使用设计模式封装一个弹窗引擎
前言
最近项目使用的一个第三方库很多线上 Bug 所以考虑换一个第三方库了,结果去除依赖之后导致基本每个页面都要修改,项目全部爆红,人都麻了,悔不该当初图方便没有使用引擎类啊。
第三方库提供基本的各种功能,引擎类封装一层给自己的项目预定特定的效果,上层应用只需要调用引擎即可实现效果,不需要关心底层的实现,不需要引用第三方的依赖和类库。当我们第三方库升级或替换的时候,只需要修改引擎类即可。
下面我以弹窗库的封装为例,封装一个弹窗引擎库,下来就一起来看看吧。
一、工厂模式实现不同弹窗布局的创建
其实作为一上层应用,我只关心弹窗的类型,方向,动画,是否居中,依附在哪,简单生命周期回调,控制展示和关闭即可。
以本文的第三方库 [Xpopup] 为例。它的 Api 是很多的各种方法,但是我们项目UI风格固定,只用得到那么几种。当然你完全可以换成自己的封装库或者Android原生的Dialog,WindowPoppup 都可以。
我们以常用的 底部弹窗,居中弹窗,局部下拉选,全屏下拉选,全屏弹窗这五种弹窗类型,由于传递进来一个布局我不知道是哪一种类型,所以根据弹窗类型我们要动态的返回对应的布局。
所以我们以工厂模式来创建对应的实例。
interface IPopupViewCreator<VB : ViewBinding> {
fun create(viewBinding: ((LayoutInflater) -> VB)?): BasePopupView
}
那么基本的五种类型弹窗的创建器如下:
默认下拉选弹窗:
private open class OpenAttachPopupView<VB : ViewBinding>(
context: Context,
private val viewBinding: ((LayoutInflater) -> VB)?,
private val width: Int,
private val height: Int,
private val maxWidth: Int,
private val maxHeight: Int,
private val onCreateListener: ((VB, IPopupController) -> Unit)?,
private val onDismissListener: (() -> Unit)?,
) : AttachPopupView(context) {
//弹窗控制器-常见的功能
private val closeControl = IPopupController {
dismiss() }
lateinit var mBinding: VB
override fun addInnerContent() {
if (viewBinding != null) {
mBinding = viewBinding.invoke(LayoutInflater.from(context))
attachPopupContainer.addView(mBinding.root)
} else {
super.addInnerContent()
}
}
override fun getPopupWidth(): Int {
return if (width != 0) width else super.getPopupWidth()
}
override fun getPopupHeight(): Int {
return if (height != 0) height else super.getPopupHeight()
}
// 如果需要覆写 getMaxWidth 和 getMaxHeight,可以提供自定义的最大宽高
override fun getMaxWidth(): Int {
return if (maxWidth != 0) maxWidth else super.getMaxWidth()
}
override fun getMaxHeight(): Int {
return if (maxHeight != 0) maxHeight else super.getMaxHeight()
}
override fun onCreate() {
super.onCreate()
onCreateListener?.invoke(mBinding, closeControl)
}
override fun onDismiss() {
super.onDismiss()
onDismissListener?.invoke()
}
}
class AttachPopupViewCreator<VB : ViewBinding>(
private val context: Context,
private val width: Int,
private val height: Int,
private val maxWidth: Int,
private val maxHeight: Int,
private val onCreateListener: ((VB, IPopupController) -> Unit)?,
private val onDismissListener: (() -> Unit)?,
) : IPopupViewCreator<VB> {
override fun create(viewBinding: ((LayoutInflater) -> VB)?): BasePopupView {
return OpenAttachPopupView<VB>(
context,
viewBinding,
width, height,
maxWidth, maxHeight,
onCreateListener, onDismissListener
)
}
}
全屏弹窗:
private open class OpenFullScreenPopupView<VB : ViewBinding>(
context: Context,
private val viewBinding: ((LayoutInflater) -> VB)?,
private val onCreateListener: ((VB, IPopupController) -> Unit)?,
private val onDismissListener: (() -> Unit)?,
) : FullScreenPopupView(context) {
//弹窗控制器-常见的功能
private val closeControl = IPopupController {
dismiss() }
lateinit var mBinding: VB
override fun addInnerContent() {
if (viewBinding != null) {
mBinding = viewBinding.invoke(LayoutInflater.from(context))
fullPopupContainer.addView(mBinding.root)
} else {
super.addInnerContent()
}
}
override fun onCreate() {
super.onCreate()
onCreateListener?.invoke(mBinding, closeControl)
}
override fun onDismiss() {
super.onDismiss()
onDismissListener?.invoke()
}
}
class FullScreenPopupViewCreator<VB : ViewBinding>(
private val context: Context,
private val onCreateListener: ((VB, IPopupController) -> Unit)?,
private val onDismissListener: (() -> Unit)?,
) : IPopupViewCreator<VB> {
override fun create( viewBinding: ((LayoutInflater) -> VB)?): BasePopupView {
return OpenFullScreenPopupView(
context,
viewBinding,
onCreateListener, onDismissListener
)
}
}
全屏下拉选弹窗:
private open class OpenPartPopupView<VB : ViewBinding>(
context: Context,
private val viewBinding: ((LayoutInflater) -> VB)?,
private val height: Int,
private val maxHeight: Int,
private val onCreateListener: ((VB, IPopupController) -> Unit)?,
private val onDismissListener: (() -> Unit)?,
) : PartShadowPopupView(context) {
//弹窗控制器-常见的功能
private val closeControl = IPopupController {
dismiss() }
lateinit var mBinding: VB
override fun addInnerContent() {
if (viewBinding != null) {
mBinding = viewBinding.invoke(LayoutInflater.from(context))
attachPopupContainer.addView(mBinding.root)
} else {
super.addInnerContent()
}
}
override fun getPopupHeight(): Int {
return if (height != 0) height else super.getPopupHeight()
}
override fun getMaxHeight(): Int {
return if (maxHeight != 0) maxHeight else super.getMaxHeight()
}
override fun onCreate() {
super.onCreate()
onCreateListener?.invoke(mBinding, closeControl)
}
override fun onDismiss() {
super.onDismiss()
onDismissListener



被折叠的 条评论
为什么被折叠?



