一个使用ViewBinding封装的Dialog

32 阅读1分钟

一个使用ViewBinding封装的Dialog,使用方便简单

话不多说,直接上干货

使用方法

showXDialog(DialogVersionUpgrdeBinding::inflate) {
    setCanceledOnTouchOutside(true)
    setDimAmount(0.7f)
    setWidth(300)
    setGravity(Gravity.CENTER)
    setAnimation(R.style.animate_dialog)
    onDismiss {
        Log.e("dialog", "dismiss")
    }
    setOnKeyListener { dialog,keyCode, event -> false }
    binding.apply {
        tvConfirm.onClick {
            toast("立即升级")
            dismiss()
        }
        tvCancel.onClick {
            toast("稍后再说")
            dismiss()
        }
    }

}

实现方法

1、先封装一个 DialogScope
class DialogScope<VB : ViewBinding>(
    val dialog: Dialog,
    val binding: VB
) {

    private val window get() = dialog.window
    private val context get() = dialog.context

    private val params: WindowManager.LayoutParams?
        get() = window?.attributes

    /* ---------------- 基础 ---------------- */

    fun setCancelable(flag: Boolean) {
        dialog.setCancelable(flag)
    }

    fun setCanceledOnTouchOutside(flag: Boolean) {
        dialog.setCanceledOnTouchOutside(flag)
    }

    fun setDimAmount(amount: Float) {
        window?.setDimAmount(amount)
    }

    fun dismiss() {
        dialog.dismiss()
    }

    /* ---------------- 固定宽高 ---------------- */

    fun setWidth(widthDp: Int) {
        params?.let {
            it.width = widthDp.dp
            window?.attributes = it
        }
    }

    fun setHeight(heightDp: Int) {
        params?.let {
            it.height = heightDp.dp
            window?.attributes = it
        }
    }

    /* ---------------- 屏幕比例 ---------------- */

    fun setScreenWidthAspect(aspect: Float) {
        val screenWidth = context.resources.displayMetrics.widthPixels
        params?.let {
            it.width = (screenWidth * aspect).toInt()
            window?.attributes = it
        }
    }

    fun setScreenHeightAspect(aspect: Float) {
        val screenHeight = context.resources.displayMetrics.heightPixels
        params?.let {
            it.height = (screenHeight * aspect).toInt()
            window?.attributes = it
        }
    }

    /* ---------------- 重力 ---------------- */

    fun setGravity(gravity: Int) {
        params?.let {
            it.gravity = gravity
            window?.attributes = it
        }
    }
}

2、再封装Dialog


class XDialog<VB : ViewBinding>(
    private val inflater: (LayoutInflater) -> VB
) : DialogFragment() {

    private var _binding: VB? = null
    private val binding get() = _binding!!

    private var dslBlock: (DialogScope<VB>.() -> Unit)? = null

    fun setDsl(block: DialogScope<VB>.() -> Unit) {
        dslBlock = block
    }

    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
        return Dialog(requireContext()).apply {
            requestWindowFeature(Window.FEATURE_NO_TITLE) // 防止 requestFeature() 异常
        }
    }

    override fun onResume() {
        //去除左右边距
        dialog!!.window!!.decorView.setPadding(0, 0, 0, 0)
        super.onResume()
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        _binding = this.inflater.invoke(inflater)
        return binding.root
    }

    override fun onStart() {
        super.onStart()
        dialog?.window?.let { window ->
            window.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
            // 先给一个默认值,防止 wrap_content 失效
            val params = window.attributes
            params.width = ViewGroup.LayoutParams.WRAP_CONTENT
            params.height = ViewGroup.LayoutParams.WRAP_CONTENT
            window.attributes = params
        }
        dialog?.let {
            dslBlock?.invoke(DialogScope(it, binding))
        }
    }

    override fun onDestroyView() {
        super.onDestroyView()
        _binding = null
    }
}
如果有帮助到你,请点赞收藏
最后附上源码地址

Gitee地址

Screenshot_20260303_134908.png

Screenshot_20260303_134938.png

Screenshot_20260303_134958.png

Screenshot_20260303_135011.png

Screenshot_20260303_135021.png