安卓(kotlin)自定义弹出框

在安卓开发中,我们经常会遇到这种情况,就是可爱的UI们设计了一套属于我们自己风格的弹出框,为了彰显我们自己的风格,使用自动的dialog当然满足不了我们的需求,所以还是得这基础上写出我们自己的提示框,以后UI再变化,我们也只需要修改样式就好了。

1.首先我们先写好dialog的样式

custom_dialog.xml



    
    
    
        
        
    
    
        
    

2.然后定义一个CustomDialog继承Dialog,在这里定义我们自己要调用的方法等。

CustomDialog.kt

package com.xindong.rocket

import android.app.Dialog
import android.content.Context
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import android.widget.TextView

class CustomDialog : Dialog {

    constructor(context: Context) : super(context) {}
    constructor(context: Context, theme: Int) : super(context, theme) {}

    class Builder(context: Context) {
        private var title: String? = null
        private var message: String? = null
        private var contentView: View? = null
        private var positiveButtonText: String? = null
        private var negativeButtonText: String? = null
        private var singleButtonText: String? = null
        private var positiveButtonClickListener: View.OnClickListener? = null
        private var negativeButtonClickListener: View.OnClickListener? = null
        private var singleButtonClickListener: View.OnClickListener? = null

        private val layout: View
        private val dialog: CustomDialog = CustomDialog(context, R.style.CustomDialog)

        init {
            //这里传入自定义的style,直接影响此Dialog的显示效果。style具体实现见style.xml
            val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
            layout = inflater.inflate(R.layout.custom_dialog, null)
            dialog.addContentView(layout, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT))
        }

        fun setTitle(title: String): Builder{
            this.title = title
            return this
        }

        fun setMessage(message: String): Builder {
            this.message = message
            return this
        }

        fun setContentView(v: View): Builder {
            this.contentView = v
            return this
        }

        fun setPositiveButton(positiveButtonText: String, listener: View.OnClickListener): Builder {
            this.positiveButtonText = positiveButtonText
            this.positiveButtonClickListener = listener
            return this
        }

        fun setNegativeButton(negativeButtonText: String, listener: View.OnClickListener): Builder {
            this.negativeButtonText = negativeButtonText
            this.negativeButtonClickListener = listener
            return this
        }

        fun setSingleButton(singleButtonText: String, listener: View.OnClickListener): Builder {
            this.singleButtonText = singleButtonText
            this.singleButtonClickListener = listener
            return this
        }

        /**
         * 创建单按钮对话框
         * @return
         */
        fun createSingleButtonDialog(): CustomDialog {
            showSingleButton()
            layout.findViewById(R.id.singleBtn).setOnClickListener(singleButtonClickListener)
            //如果传入的按钮文字为空,则使用默认的“知道了”
            if (singleButtonText != null) {
                (layout.findViewById(R.id.singleBtn) as TextView).text = singleButtonText
            } else {
                (layout.findViewById(R.id.singleBtn) as TextView).text = "知道了"
            }
            create()
            return dialog
        }

        /**
         * 创建双按钮对话框
         * @return
         */
        fun createTwoButtonDialog(): CustomDialog {
            showTwoButton()
            layout.findViewById(R.id.positiveBtn).setOnClickListener(positiveButtonClickListener)
            layout.findViewById(R.id.negativeBtn).setOnClickListener(negativeButtonClickListener)
            //如果传入的按钮文字为空,则使用默认的“确定”和“取消”
            if (positiveButtonText != null) {
                (layout.findViewById(R.id.positiveBtn) as TextView).text = positiveButtonText
            } else {
                (layout.findViewById(R.id.positiveBtn) as TextView).text = "确定"
            }
            if (negativeButtonText != null) {
                (layout.findViewById(R.id.negativeBtn) as TextView).text = negativeButtonText
            } else {
                (layout.findViewById(R.id.negativeBtn) as TextView).text = "取消"
            }
            create()
            return dialog
        }

        /**
         * 单按钮对话框和双按钮对话框的公共部分在这里设置
         */
        private fun create() {
            if (message != null) {      //设置提示内容
                (layout.findViewById(R.id.message) as TextView).text = message
            } else if (contentView != null) {       //如果使用Builder的setContentview()方法传入了布局,则使用传入的布局
                (layout.findViewById(R.id.content) as LinearLayout).removeAllViews()
                (layout.findViewById(R.id.content) as LinearLayout)
                        .addView(contentView, ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT))
            }
            if(title!=null && title!!.isNotEmpty()){
                (layout.findViewById(R.id.title) as TextView).text = title
                showTitle()
            }
            dialog.setContentView(layout)
            dialog.setCancelable(true)     //用户可以点击手机Back键取消对话框显示
            dialog.setCanceledOnTouchOutside(false)        //用户不能通过点击对话框之外的地方取消对话框显示
        }

        /**
         * 显示双按钮布局,隐藏单按钮
         */
        private fun showTwoButton() {
            layout.findViewById(R.id.singleButtonLayout).visibility = View.GONE
            layout.findViewById(R.id.twoButtonLayout).visibility = View.VISIBLE
        }

        /**
         * 显示单按钮布局,隐藏双按钮
         */
        private fun showSingleButton() {
            layout.findViewById(R.id.singleButtonLayout).visibility = View.VISIBLE
            layout.findViewById(R.id.twoButtonLayout).visibility = View.GONE
        }

        private fun showTitle() {
            layout.findViewById(R.id.title).visibility = View.VISIBLE
        }

    }
}

3.设置dialog的背景

drawable/comment_dialog_bg.xml



    
    

4.将上面写好的dialog背景设置给一个style

style.xml

 

5.最后在activity里定义并调用自定义dialog的方法。

MainActivty.kt

private var builderForCustom: CustomDialog.Builder? = null
    private var mDialog: CustomDialog? = null

然后在onCreate里

builderForCustom = CustomDialog.Builder(this)

定义方法

 private fun showSingleButtonDialog(title: String, alertText: String, btnText: String, onClickListener:View.OnClickListener) {
        mDialog = builderForCustom!!.setTitle(title)
                .setMessage(alertText)
                .setSingleButton(btnText, onClickListener)
                .createSingleButtonDialog()
        mDialog!!.show()
    }

 private fun showTwoButtonDialog(title: String, alertText: String, confirmText: String, cancelText: String, conFirmListener: View.OnClickListener, cancelListener: View.OnClickListener) {
        mDialog = builderForCustom!!.setTitle(title)
                .setMessage(alertText)
                .setPositiveButton(confirmText, conFirmListener)
                .setNegativeButton(cancelText, cancelListener)
                .createTwoButtonDialog()
        mDialog!!.show()
    }

调用方法

showTwoButtonDialog("", "这是自定义弹出框","确定", "取消", View.OnClickListener {
            // 操作
            mDialog!!.dismiss()
        },View.OnClickListener {
            // 操作
            mDialog!!.dismiss()
        })

调用单个按钮的方法也是同样的方式。

如果是在fragment调用activity里定义的弹出框方法,则可以单独定义一个关闭弹出框的方法,或者将mDialog设置为公共属性。

效果如下
be902c2e8e6aa2e10cd9c4d4c125814.jpg

你可能感兴趣的:(android,kotlin,dialog,自定义)