把弹窗拆成"固定骨架 + 可替换内容插槽",新弹窗只要提供一个布局,风格自动统一。
前言
一个 App 里弹窗特别多:底部选择器、确认框、输入框、信息展示......如果每个弹窗都从零写一个布局、各自调样式,结果就是------颜色深浅不一、圆角大小不一、标题字体不一,看起来像三个团队做的。
这篇文章讲一种插槽模式:先定义一份统一的弹窗骨架(标题栏 + 内容区 + 可选的操作栏),内容区留一个"插槽",不同弹窗只需要往插槽里塞各自的布局,风格就天然统一了。
一、痛点:每个弹窗各写各的
最原始的做法是每个弹窗一个独立的布局文件,自己管标题、自己管按钮、自己设背景圆角:
xml
<!-- 弹窗 A 的布局 -->
<LinearLayout ...>
<TextView android:text="提示" .../>
<TextView android:text="确认删除?" .../>
<Button android:text="确定" .../>
</LinearLayout>
弹窗 A、B、C 各自这样写,标题样式、按钮样式、圆角完全靠每个开发者"记得保持统一"。一旦有人改了主题色,所有弹窗要挨个改。插槽模式要解决的就是这个"重复 + 不统一"。
二、骨架:一份统一布局 + 一个内容插槽
定义一份"通用弹窗骨架"布局,结构固定:
标题栏(可隐藏)
────────────
内容区(插槽)
────────────
操作栏(可隐藏:确定/取消按钮)
在代码里,弹窗基类暴露两个"槽位"方法:一个提供内容布局,一个提供标题栏布局(可选)。子类只需重写这些方法,往槽位里放自己的东西:
kotlin
abstract class BaseBottomDialog : BottomSheetDialogFragment() {
// 子类重写:返回自己的内容布局
protected abstract fun contentView(parent: ViewGroup): View
// 子类可选重写:返回标题栏布局(默认不显示)
protected open fun titleView(parent: ViewGroup): View? = null
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
): View {
// 加载统一骨架
val root = inflater.inflate(R.layout.dialog_skeleton, container, false)
// 往插槽里填内容
val contentSlot = root.findViewById<FrameLayout>(R.id.content_slot)
contentSlot.addView(contentView(contentSlot))
// 可选标题
val titleSlot = root.findViewById<FrameLayout>(R.id.title_slot)
titleView(contentSlot)?.let { titleSlot.addView(it) }
return root
}
}
骨架布局里,标题栏和操作栏默认 gone(隐藏),子类需要时才显示。所有弹窗共用这份骨架,所以圆角、背景、标题样式只有一份,改一次全生效。
三、内容插槽:子类只写"中间那块"
具体弹窗子类变得非常轻,只需重写 contentView 提供中间内容:
kotlin
class ConfirmDeleteDialog(
private val onConfirm: () -> Unit
) : BaseBottomDialog() {
override fun contentView(parent: ViewGroup): View {
return inflater(parent).inflate(R.layout.content_confirm, parent, false)
}
override fun onConfirmClicked() {
onConfirm()
dismiss()
}
}
要做一个新弹窗,只需要:新建一个内容布局 + 继承骨架 + 重写一个方法。不需要关心标题、按钮、圆角长什么样,这些全在骨架里定好了。
四、操作栏:确定/取消的复用
确定/取消按钮也在骨架里,通过回调让子类挂接自己的逻辑:
kotlin
// 骨架里提供统一的确定/取消回调
interface ActionListener {
fun onConfirm()
fun onCancel() {}
}
子类实现 onConfirm/onCancel,骨架负责绑定按钮点击和默认样式。于是所有弹窗的按钮都是同一个样式、同一个间距,点按反馈也统一。
结论
- 弹窗重复 + 不统一的根因是每个弹窗各自写布局,插槽模式把"骨架"和"内容"分离。
- 统一骨架(标题 + 内容插槽 + 操作栏)一份定义、处处复用,改主题只需改骨架。
- 子类只需重写"内容插槽"方法,新弹窗成本 = 一个新布局 + 一个继承类。
- 操作栏用统一回调挂接,按钮样式、点击反馈全局一致。
- 插槽/模板模式的本质是把变化的(内容)和不变的(骨架)拆开,这套思路也适用于统一的空页面、列表项、引导页。
你项目里弹窗风格不统一的问题,是用插槽模式还是别的方案解决的?欢迎在评论区聊聊你的做法。
关键词标签 :#Android #Dialog #BottomSheetDialog #插槽模式 #弹窗 #统一风格 #模板模式 #Kotlin