安卓(kotlin)自定义弹出框

叻妮

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

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

custom_dialog.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/content"
    android:layout_width="280dp"
    android:layout_height="wrap_content"
    android:paddingRight="24dp"
    android:paddingLeft="24dp"
    android:paddingTop="21dp"
    android:paddingBottom="21dp"
    android:orientation="vertical">
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textColor="#deffffff"
        android:letterSpacing="0.03"
        android:lineSpacingExtra="8sp"
        android:text="提示"
        android:layout_marginTop="6dp"
        android:layout_marginBottom="15dp"
        android:visibility="gone"/>
    <TextView
        android:id="@+id/message"
        android:layout_width="256dp"
        android:layout_height="wrap_content"
        android:textSize="14sp"
        android:textColor="#99ffffff"
        android:letterSpacing="0.02"
        android:lineSpacingExtra="6sp"
        android:text="这是自定义弹出框"
        />
    <RelativeLayout
        android:id="@+id/twoButtonLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="31dp">
        <TextView
            android:id="@+id/negativeBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="#138ef0"
            android:letterSpacing="0.09"
            android:lineSpacingExtra="2sp"
            android:text="取消"
            android:layout_alignParentRight="true"
            android:layout_marginRight="89dp"
            android:padding="10dp"
            android:focusableInTouchMode="false"
            />
        <TextView
            android:id="@+id/positiveBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="#138ef0"
            android:letterSpacing="0.09"
            android:lineSpacingExtra="2sp"
            android:text="满意"
            android:layout_alignParentRight="true"
            android:paddingBottom="10dp"
            android:paddingTop="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="5dp"
            />
    </RelativeLayout>
    <RelativeLayout
        android:id="@+id/singleButtonLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="41dp">
        <TextView
            android:id="@+id/singleBtn"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:textColor="#138ef0"
            android:letterSpacing="0.09"
            android:lineSpacingExtra="2sp"
            android:text="确定"
            android:layout_alignParentRight="true"
            android:paddingBottom="10dp"
            android:paddingTop="10dp"
            android:paddingLeft="10dp"
            android:paddingRight="5dp"
            />
    </RelativeLayout>
</LinearLayout>

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<View>(R.id.singleBtn).setOnClickListener(singleButtonClickListener)
            //如果传入的按钮文字为空,则使用默认的“知道了”
            if (singleButtonText != null) {
                (layout.findViewById<View>(R.id.singleBtn) as TextView).text = singleButtonText
            } else {
                (layout.findViewById<View>(R.id.singleBtn) as TextView).text = "知道了"
            }
            create()
            return dialog
        }

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

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

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

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

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

    }
}

3.设置dialog的背景

drawable/comment_dialog_bg.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
    <corners android:radius="4dp"/>
    <solid android:color="#282a34"/>
</shape>

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

style.xml

 <style name="CustomDialog" parent="android:Theme.Dialog">
        <item name="android:windowBackground">@drawable/comment_dialog_bg</item>
    </style>

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

阅读 5.3k

在coding的海洋潜水

4 声望
2 粉丝
0 条评论

在coding的海洋潜水

4 声望
2 粉丝
文章目录
宣传栏