如何在Android中为Dialog和BottomSheetDialog创建可复用的Kotlin扩展函数?
如何在Android中为Dialog和BottomSheetDialog创建可复用的Kotlin扩展函数?
兄弟我太懂你这种感受了!每次写Dialog或者BottomSheetDialog,都要重复写ViewBinding初始化、设置可取消性、调样式这些模板代码,完全是在做无意义的重复劳动,把本该放在业务逻辑上的精力都分散了。别担心,用Kotlin的扩展函数完全可以把这些重复逻辑封装起来,以后只用专注处理业务就行,下面我给你一步步讲怎么实现:
一、先封装Dialog的通用基础配置
首先我们可以先写一个扩展函数,把Dialog共有的配置(比如是否可取消、窗口样式)抽出来,这样所有Dialog都能复用:
import android.app.Dialog import android.graphics.Color import android.graphics.drawable.ColorDrawable import android.view.ViewGroup fun Dialog.setupBasicConfig( isCancelable: Boolean = true, isCanceledOnTouchOutside: Boolean = true ): Dialog { this.isCancelable = isCancelable this.isCanceledOnTouchOutside = isCanceledOnTouchOutside // 这里可以根据项目需求自定义窗口样式,比如全屏宽度、透明背景 window?.apply { setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT)) } return this }
二、结合ViewBinding的Dialog创建扩展
接下来我们再写一个更实用的扩展函数,直接帮你完成ViewBinding的初始化和Dialog的创建,不用每次都手动写inflate和setContentView:
import android.content.Context import android.view.LayoutInflater import androidx.viewbinding.ViewBinding inline fun <reified T : ViewBinding> Context.createDialog( themeResId: Int = R.style.AppDialogTheme, // 替换成你项目的Dialog主题 isCancelable: Boolean = true, crossinline onViewCreated: (T) -> Unit ): Dialog { // 通过反射自动初始化ViewBinding,不用每个Dialog都写重复的inflate代码 val binding = T::class.java.getMethod("inflate", LayoutInflater::class.java) .invoke(null, LayoutInflater.from(this)) as T val dialog = Dialog(this, themeResId) dialog.setContentView(binding.root) dialog.setupBasicConfig(isCancelable) // 复用上面的基础配置 // 把binding传给业务逻辑的lambda,你只需要在这里处理业务 onViewCreated(binding) return dialog }
三、BottomSheetDialog的专属扩展
BottomSheetDialog有自己的特殊属性(比如全屏宽度、BottomSheetBehavior的配置),我们可以在Dialog扩展的基础上,再写它的专属扩展:
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetBehavior import android.view.ViewGroup fun BottomSheetDialog.setupFullWidth() { // 配置BottomSheetBehavior,让BottomSheet撑满屏幕宽度 this.behavior.apply { isFitToContents = false setExpandedOffset(0) state = BottomSheetBehavior.STATE_EXPANDED } window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) } // 同样,结合ViewBinding写一个BottomSheetDialog的创建扩展 inline fun <reified T : ViewBinding> Context.createBottomSheetDialog( themeResId: Int = R.style.AppBottomSheetDialogTheme, // 替换成你项目的BottomSheet主题 isCancelable: Boolean = true, crossinline onViewCreated: (T) -> Unit ): BottomSheetDialog { val binding = T::class.java.getMethod("inflate", LayoutInflater::class.java) .invoke(null, LayoutInflater.from(this)) as T val bottomSheet = BottomSheetDialog(this, themeResId) bottomSheet.setContentView(binding.root) bottomSheet.setupBasicConfig(isCancelable) // 复用Dialog的基础配置 bottomSheet.setupFullWidth() // 应用BottomSheet的专属配置 onViewCreated(binding) return bottomSheet }
四、怎么用这些扩展?
现在你创建Dialog或者BottomSheetDialog就超级简单了,只用专注写业务逻辑就行:
// 示例:创建一个普通Dialog createDialog<DialogSampleBinding> { binding -> // 这里只处理业务逻辑,比如设置文本、按钮点击 binding.tvDialogTitle.text = "提示" binding.btnConfirm.setOnClickListener { // 处理确认逻辑 dismiss() } }.show() // 示例:创建BottomSheetDialog createBottomSheetDialog<SheetSampleBinding> { binding -> binding.tvSheetContent.text = "这是一个全屏宽度的BottomSheet" binding.btnClose.setOnClickListener { dismiss() } }.show()
五、一些小提示
- 主题资源:上面的
R.style.AppDialogTheme和R.style.AppBottomSheetDialogTheme要替换成你项目里自定义的主题,比如设置圆角、背景色、动画等 - 灵活调整:如果需要更个性化的配置,可以给扩展函数加参数,比如是否全屏、是否显示动画等
- 反射替代:如果你觉得用反射初始化ViewBinding不太放心,也可以改成手动传入Binding的inflate函数,比如把
createDialog的参数改成crossinline inflate: (LayoutInflater) -> T,这样就更灵活了
内容来源于stack exchange
相关产品推荐
相关产品推荐

