Kotlin - ViewBinding + DialogFragment封装基础弹框

针对目前弹框的使用比较频繁,现在动手封装一个通用弹框的基类,使用ViewBinding +DialogFragment,希望能够帮到大家。

1.onCreate()方法中添加Style.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(STYLE_NORMAL, R.style.BaseDialogStyle)
}

BaseDialogStyle代码如下(大家根据自己的需求进行修改):

  <style name="BaseDialogStyle" parent="Theme.MaterialComponents.DayNight.Dialog">
    <item name="android:windowBackground">@android:color/transparent</item>
    <item name="android:windowFrame">@null</item>
    <item name="android:windowNoTitle">true</item>
    <item name="android:windowFullscreen">true</item>
    <item name="android:windowTranslucentStatus">true</item><!-- 解决全屏时状态栏变黑 -->
    <item name="android:backgroundDimEnabled">true</item>   <!-- 是否允许背景模糊 -->
    <item name="android:windowIsTranslucent">true</item>    <!-- 是否半透明 -->
    <item name="android:windowIsFloating">true</item>       <!-- 是否浮现在activity之上 -->
    <item name="android:windowContentOverlay">@null</item>  <!-- 是否有遮盖 -->
    <item name="android:backgroundDimAmount">0.6</item>     <!-- 设置背景模糊的透明度-->
</style>

2. 弹框核心代码:

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
    ): View? {

    dialog?.setCanceledOnTouchOutside(isOnTouchOutSide)
    dialog?.setOnKeyListener { _, keyCode, _ -> !isOnBackPress && keyCode == KeyEvent.KEYCODE_BACK }

    initBinding(container)
    initData()
    return viewBinding?.root
}

3. 在onStart()方法中可以动态设置宽高和透明度以及弹框的位置(上下左右),弹框动画大家可以根据需要自行添加:

override fun onStart() {
    super.onStart()
    setSite()
}

private fun setSite() {
    val mWindow = dialog?.window
    val mLayoutParams = mWindow?.attributes
    mLayoutParams?.width = windowWidth
    mLayoutParams?.height = windowHeight
    mLayoutParams?.gravity = viewSite
    mWindow?.attributes = mLayoutParams
    mWindow?.setDimAmount(alpha)
}

4. 完整代码如下:

abstract class BaseDialog<V : ViewBinding> constructor(
    private val isOnTouchOutSide: Boolean = true,
    private val isOnBackPress: Boolean = true,
    private val viewSite: Int = Gravity.CENTER,
    private val windowWidth: Int = ViewGroup.LayoutParams.WRAP_CONTENT,
    private val windowHeight: Int = ViewGroup.LayoutParams.WRAP_CONTENT,
    private val alpha: Float = 0.6f
) : DialogFragment() {
protected val viewBinding: V?
     get() = _binding!!
private var _binding: V? = null
protected abstract fun initData()

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setStyle(STYLE_NORMAL, R.style.BaseDialogStyle)
}

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    dialog?.setCanceledOnTouchOutside(isOnTouchOutSide)
    dialog?.setOnKeyListener { _, keyCode, _ -> !isOnBackPress && keyCode == KeyEvent.KEYCODE_BACK }
    initBinding(container)
    initData()
    return viewBinding?.root
}

override fun onStart() {
    super.onStart()
    setSite()
}

private fun setSite() {
    val mWindow = dialog?.window
    val mLayoutParams = mWindow?.attributes
    mLayoutParams?.width = windowWidth
    mLayoutParams?.height = windowHeight
    mLayoutParams?.gravity = viewSite
    mWindow?.attributes = mLayoutParams
    mWindow?.setDimAmount(alpha)
}

/**
 * 初始化viewBinding
 */
private fun initBinding(container: ViewGroup?) {
    val type = javaClass.genericSuperclass
    val clazz = (type as ParameterizedType).actualTypeArguments[0] as Class<V>
    val method = clazz.getMethod(
        "inflate",
        LayoutInflater::class.java,
        ViewGroup::class.java,
        Boolean::class.java
    )
    _binding = method.invoke(null, layoutInflater, container, false) as V
}
}

最后,希望对大家有所帮助,如果有不对的地方,欢迎大家指正。谢谢!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容