Android通用DialogFragment

前言

在开发过程中,我们会经常使用对话框,为了提高开发效率,于是我使用DialogFragment封装了一个通过的对话框。

为什么使用DialogFragment

首先在使用 DialogFragment之前,我们创建对话框一般都会采用Dialog的形式,并且从编写代码的角度来看,Dialog使用起来也较为简单,但Android 官方推荐使用 DialogFragment 来代替 Dialog。
DialogFragment 有着Dialog 所没有的特性在手机配置变化,导致Activity需要重新创建时,例如旋屏,基于DialogFragment的对话框将会由FragmentManager自动重建,然而基于Dialog实现的对话框则没有这样的能力),可以让它具有更高的可复用性(降低耦合)和更好的便利性。

在这里插入图片描述在这里插入图片描述

通用DialogFragment代码:

class CommonDialog: DialogFragment() {
    
    private var mLayoutResId = 0
    private var mDimAmount = 0.5f //背景昏暗度
    private var mShowBottomEnable= false //是否底部显示
    private var mMargin = 0 //左右边距
    private var mAnimStyle = 0 //进入退出动画
    private var mOutCancel = true //点击外部取消
    var mContext: Context? = null
    private var mWidth = 0
    private var mHeight = 0
    private var convertListener:ViewConvertListener?=null

    override fun onAttach(context: Context) {
        super.onAttach(context)
        mContext = context
    }

    override fun onCreate(@Nullable savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setStyle(STYLE_NO_TITLE, setDialogStyle())
    }

    @Nullable
    override fun onCreateView(inflater: LayoutInflater, @Nullable container: ViewGroup?, @Nullable savedInstanceState: Bundle?): View? {
        if (mLayoutResId>0){
            val view: View = inflater.inflate(mLayoutResId, container, false)
            convertListener?.convertView(DialogViewHolder.create(view), this)
            return view
        }
        return null
    }

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

    private fun initParams() {
        val window: Window? = dialog!!.window
        if (window != null) {
            val params: WindowManager.LayoutParams = window.attributes
            params.dimAmount = mDimAmount

            //设置dialog显示位置
            if (mShowBottomEnable) {
                params.gravity = Gravity.BOTTOM
            }

            //设置dialog宽高
            params.width=if(mWidth==0) getScreenWidth(context!!) - 2 * dp2px(context!!, mMargin.toFloat()) else dp2px(context!!, mWidth.toFloat())
            params.height=if(mHeight == 0) WindowManager.LayoutParams.WRAP_CONTENT else dp2px(context!!, mHeight.toFloat())

            //设置dialog动画
            if (mAnimStyle != 0) {
                window.setWindowAnimations(mAnimStyle)
            }
            window.attributes = params
        }
        //isCancelable = mOutCancel //设置无效
        dialog?.setCancelable(mOutCancel)
        dialog?.setCanceledOnTouchOutside(mOutCancel)
    }

    /**
     * 设置背景昏暗度
     *
     * @param dimAmount
     * @return
     */
    fun setDimAmount(@FloatRange(from = 0.0, to = 1.0) dimAmount: Float): CommonDialog? {
        mDimAmount = dimAmount
        return this
    }

    /**
     * 是否显示底部
     *
     * @param showBottom
     * @return
     */
    fun setShowBottom(showBottom: Boolean): CommonDialog? {
        mShowBottomEnable = showBottom
        return this
    }

    /**
     * 设置宽高
     *
     * @param width
     * @param height
     * @return
     */
    fun setDialogSize(width: Int, height: Int): CommonDialog? {
        mWidth = width
        mHeight = height
        return this
    }

    /**
     * 设置左右margin
     *
     * @param margin
     * @return
     */
    fun setDialogMargin(margin: Int): CommonDialog? {
        mMargin = margin
        return this
    }

    /**
     * 设置进入退出动画
     *
     * @param animStyle
     * @return
     */
    fun setAnimStyle(@StyleRes animStyle: Int): CommonDialog? {
        mAnimStyle = animStyle
        return this
    }

    /**
     * 设置是否点击外部取消
     *
     * @param outCancel
     * @return
     */
    fun setOutCancel(outCancel: Boolean): CommonDialog? {
        mOutCancel = outCancel
        return this
    }

    fun show(manager: FragmentManager): CommonDialog? {
        super.show(manager, System.currentTimeMillis().toString())
        return this
    }

    /**
     * 设置dialog布局
     *
     * @return
     */
    fun setDialogLayoutId(layoutId: Int=0){
        mLayoutResId=layoutId
    }

    /**
     * 设置dialog样式
     *
     * @return
     */
    fun setDialogStyle(style:Int=R.style.fullScreenDialog): Int{
        return style
    }

    fun setConvertListener(convertListener: ViewConvertListener): CommonDialog? {
        this.convertListener = convertListener
        return this
    }

    /**
     * 获取屏幕宽度
     *
     * @param context
     * @return
     */
    fun getScreenWidth(context: Context): Int {
        val displayMetrics: DisplayMetrics = context.resources.displayMetrics
        return displayMetrics.widthPixels
    }

    fun dp2px(context: Context, dipValue: Float): Int {
        val scale: Float = context.resources.displayMetrics.density
        return (dipValue * scale + 0.5f).toInt()
    }

    interface ViewConvertListener{
        fun convertView(holder: DialogViewHolder, dialog: CommonDialog)
    }

}

DialogViewHolder

class DialogViewHolder(view: View) {

    private var views: SparseArray<View>? = null
    private var convertView: View? = null

    init {
        convertView = view
        views = SparseArray()
    }

    companion object{
        fun create(view: View): DialogViewHolder {
            return DialogViewHolder(view)
        }
    }

    /**
     * 获取View
     * @param viewId
     * @param <T>
     * */
    fun <T : View> getView(@IdRes viewId: Int): T {
        var view: View? = views!![viewId]
        if (view == null) {
            view = convertView?.findViewById(viewId)
            views!!.put(viewId, view)
        }
        return view as T
    }

    /**
     * 设置文本
     *
     * @param viewId
     * @param text
     */
    fun setText(viewId: Int, text: String?) {
        val textView: TextView = getView(viewId)
        textView.text = text
    }

    /**
     * 设置字体颜色
     *
     * @param viewId
     * @param colorId
     */
    fun setTextColor(viewId: Int, colorId: Int) {
        val textView: TextView = getView(viewId)
        textView.setTextColor(colorId)
    }

    /**
     * 设置背景图片
     *
     * @param viewId
     * @param resId
     */
    fun setBackgroundResource(viewId: Int, resId: Int) {
        val view: View = getView(viewId)
        view.setBackgroundResource(resId)
    }

    /**
     * 设置背景颜色
     *
     * @param viewId
     * @param colorId
     */
    fun setBackgroundColor(viewId: Int, colorId: Int) {
        val view: View = getView(viewId)
        view.setBackgroundColor(colorId)
    }

    /**
     * 设置点击事件
     *
     * @param viewId
     * @param listener
     */
    fun setOnClickListener(viewId: Int, callback: () -> Unit) {
        val view: View = getView(viewId)
        view.setOnClickListener {
            callback()
        }
    }

    /**
     * 显示隐藏View
     * @param viewId
     * @param visibility
     */
    fun setVisibility(@IdRes viewId: Int, visibility: Int){
        val view: View = getView(viewId)
        if (visibility!=view.visibility){
            view.visibility = visibility
        }
    }
}

使用CommonDialog

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        tv_sure.setOnClickListener {
          confirm()
        }
        tv_comment.setOnClickListener {
           comment()
        }
    }

    private fun confirm(){
        CommonDialog().run {
            setDialogLayoutId(R.layout.layout_dialog_confirm)
            setOutCancel(false)
            setDialogMargin(30)
            setConvertListener(object :CommonDialog.ViewConvertListener{
                override fun convertView(holder: DialogViewHolder, dialog: CommonDialog) {
                    holder.setOnClickListener(R.id.tv_confirm) {
                        dialog.dismissAllowingStateLoss()
                    }
                    holder.setOnClickListener(R.id.tv_cancel) {
                        dialog.dismissAllowingStateLoss()
                    }
                }
            })
            show(supportFragmentManager)
        }
    }

    private fun comment(){
        CommonDialog().run {
            setDialogLayoutId(R.layout.layout_dialog_comment)
            setOutCancel(false)
            setConvertListener(object :CommonDialog.ViewConvertListener{
                override fun convertView(holder: DialogViewHolder, dialog: CommonDialog) {
                    val tvPublish=holder.getView<TextView>(R.id.tv_publish)
                    val etComment=holder.getView<EditText>(R.id.et_comment)
                    tvPublish.setOnClickListener {
                        val content=etComment.text.toString()
                        if (TextUtils.isEmpty(content)){
                            Toast.makeText(mContext,"评论内容不能为空",Toast.LENGTH_SHORT).show()
                        }else{
                            Toast.makeText(mContext,content,Toast.LENGTH_SHORT).show()
                            dialog.dismissAllowingStateLoss()
                        }
                    }
                }
            })
            show(supportFragmentManager)
        }
    }
}

Github代码地址.

猜你喜欢

转载自blog.csdn.net/tanlove1314/article/details/111518799