android之自定义Dialog

前言

今天完成了之前界面课程详情页的撰写。开始写新的界面及其逻辑,其中用到了Dialog,于是开始学习Dialog,公司做法是自定义一个新类继承自Dialog,使用新布局作为这个Dialog的样子。然后每次新建这个新类,并同时设置Dialog中两个按钮的监听器。如果大家有这个基础,直接去看自定义布局,为了防止csdn下载需要积分,我直接把代码全贴出来。
界面类似于:
在这里插入图片描述
接下来要学习一下关于Dialog的用法。首先还是放几篇好文章:
1.Android Dialog的官方教程
2.android 8种对话框(Dialog)使用方法汇总
官方的教程就是给力。
Dialog是对话框的基类,但您应该避免直接实例化 Dialog,而是使用下列子类之一:
AlertDialog
此对话框可显示标题、最多三个按钮、可选择项列表或自定义布局。
DatePickerDialogTimePickerDialog
此对话框带有允许用户选择日期或时间的预定义 UI。
Android 包括另一种名为 ProgressDialog 的对话框类,可显示具有进度条的对话框。不过,如需指示加载进度或不确定的进度,则应改为遵循进度和 Activity 的设计指南,并在您的布局中使用 ProgressBar

注意事项

1.这是错误的获取context方式。

final AlertDialog.Builder builder = new AlertDialog.Builder(getApplicationContext());

应该直接传入当前所在的Activity

final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);

使用可输入的Dialog

在这里插入图片描述

 public void showEditDialog()
    {
        final EditText inputServer = new EditText(this);
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("Edit Dialog").setIcon(android.R.drawable.ic_dialog_info).setView(inputServer)
                .setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Toast.makeText(MainActivity.this,"你取消是干啥玩意?",
                                Toast.LENGTH_SHORT).show();
                    }
                });
        builder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {

            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this,inputServer.getText().toString(),
                        Toast.LENGTH_SHORT).show();
            }
        });
        builder.show();
    }

普通弹出框

在这里插入图片描述

public void showNormalDialog()
    {
        /* @setIcon 设置对话框图标
         * @setTitle 设置对话框标题
         * @setMessage 设置对话框消息提示
         * setXXX方法返回Dialog对象,因此可以链式设置属性
         */
        final AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this);
        builder.setIcon(R.mipmap.ic_launcher);
        builder.setTitle("普通弹出框");
        builder.setMessage("是否继续");
        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                Toast.makeText(MainActivity.this,"点击了确定",Toast.LENGTH_SHORT).show();
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                Toast.makeText(MainActivity.this,"点击了取消",Toast.LENGTH_SHORT).show();

            }
        });
        builder.setNeutralButton("中间的",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Toast.makeText(MainActivity.this,"点击了中间的",Toast.LENGTH_SHORT).show();

                    }
                });
        builder.create().show();


    }

列表选择框、单选框、多选框

列表选择框就使用如下方法

builder.setItems(@ArrayRes int itemsId, OnClickListener listener)

要想添加多选项(复选框)或单选项(单选按钮)列表,请分别使用 setMultiChoiceItems() 或 setSingleChoiceItems() 方法。
在这里插入图片描述
以下示例展示了如何创建如图 所示的多选列表,将选定项保存在一个 ArrayList 中:
在这里插入图片描述
在onClick中,判断是否被选择,如果被点击就添加选中的值,如果没被选中就判断该值是否在ArrayList中,如果在的话就去掉它。

@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
    mSelectedItems = new ArrayList();  // Where we track the selected items
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    // Set the dialog title
    builder.setTitle(R.string.pick_toppings)
    // Specify the list array, the items to be selected by default (null for none),
    // and the listener through which to receive callbacks when items are selected
           .setMultiChoiceItems(R.array.toppings, null,
                      new DialogInterface.OnMultiChoiceClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int which,
                       boolean isChecked) {
                   if (isChecked) {
                       // If the user checked the item, add it to the selected items
                       mSelectedItems.add(which);
                   } else if (mSelectedItems.contains(which)) {
                       // Else, if the item is already in the array, remove it
                       mSelectedItems.remove(Integer.valueOf(which));
                   }
               }
           })
    // Set the action buttons
           .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   // User clicked OK, so save the mSelectedItems results somewhere
                   // or return them to the component that opened the dialog
                   ...
               }
           })
           .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
               @Override
               public void onClick(DialogInterface dialog, int id) {
                   ...
               }
           });

    return builder.create();
}
public void showListDialog()
    {
        choice = -1;
       final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("选择一个月份")
        //这里的第二个参数是被选中的Item。
                .setSingleChoiceItems(R.array.months, 0, new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                      choice=i;
                    }
                })
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                            if (choice != -1) {
                                String month=MainActivity.this.getResources().
                                        getStringArray(R.array.months)[choice];
                                Toast.makeText(MainActivity.this,month,
                                        Toast.LENGTH_SHORT).show();
                            }
                    }
                });

        builder.create().show();
    }

自定义布局

如果您想让对话框具有自定义布局,请创建一个布局,然后通过调用 AlertDialog.Builder 对象上的 setView() 将其添加到 AlertDialog。
默认情况下,自定义布局会填充对话框窗口,但您仍然可以使用 AlertDialog.Builder 方法来添加按钮和标题。
我们也可以完全自已定义一个Dialog。
定义Dialog需要有以下几步。

1. 定义一个style

这个style是用作给Dialog设置的,会在构造函数使用。

 <style name="InfoEditDialog" parent="android:Theme.Dialog">
        <!-- 背景颜色及透明程度 -->
        <item name="android:windowBackground">@android:color/transparent</item>
        <!-- 是否半透明 -->
        <item name="android:windowIsTranslucent">false</item>
        <!-- 是否没有标题 -->
        <item name="android:windowNoTitle">true</item>
        <!-- 是否浮现在activity之上 -->
        <item name="android:windowIsFloating">true</item>
        <!-- 是否背景模糊 -->
        <item name="android:backgroundDimEnabled">false</item>
        <!-- 设置背景模糊的透明度-->
        <item name="android:backgroundDimAmount">0.5</item>
    </style>

构造函数

public InfoEditDialog(Context mContext)
    {
        super(mContext,R.style.InfoEditDialog);
        //this.mContext=mContext;
        initView(mContext);

    }

2. 定义一个xml文件

这个xml文件是作为Dialog的默认内容xml。大概样子就是这样的,包含两个EditText与两个Button。
在这里插入图片描述
代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/info_edit_dialog"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@drawable/verify_dialog_background"
    android:padding="10dp"
    >
    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="弹出框"
        android:textSize="30dp"
        android:gravity="center"
        />
    <EditText
        android:id="@+id/bank_card"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入您的银行卡号"
        android:layout_below="@+id/title"
        />
    <EditText
        android:id="@+id/id_card"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="请输入您的身份证"
        android:layout_below="@+id/bank_card"
        />
    <Button
        android:id="@+id/positive_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/id_card"
        android:layout_toLeftOf="@+id/negative_button"
        />
    <Button
        android:id="@+id/negative_button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/id_card"
        android:layout_alignParentRight="true"
        />
</RelativeLayout>

3.InfoEditDialog类

这里其实对我来说的难点就是Button的点击事件,因为其他的要写的话就是一些set和get函数。我先写一下Button的点击事件处理。比较麻烦的问题在于,你setButton时,set的linstener不是View.OnclickListener,而是DialogInterface.OnClickListener。
首先定义两个listener,

    private DialogInterface.OnClickListener mPositiveListener, mNegativeListener;

之后获取两个button的id

btn_negavite=findViewById(R.id.negative_button);
btn_positive=findViewById(R.id.positive_button);

两个listener会在setPositiveButton与setNegaviteButton时被设置。getButton()函数是获取两个button的id。setNegaviteButton会在我们使用这个Dialog的地方被调用,往往都是重新实现一下DialogInterface.OnClickListener这个接口的实例,然后将text和实例一同传入函数。

public Button getButton(int whichButton) {
        switch (whichButton) {
            case BUTTON_POSITIVE:
                return btn_positive;
            case BUTTON_NEUTRAL:
                return null;
            case BUTTON_NEGATIVE:
                return btn_negavite;
        }
        return null;
    }
public void setNegaviteButton(CharSequence text,DialogInterface.OnClickListener listener){
        Button button = getButton(BUTTON_NEGATIVE);
        if (button != null)
        {
            button.setText(text);
            mNegativeListener=listener;
        }
    }

这里举一个在Activity中的实例。

 infoEditDialog.setPositiveButton("确定", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialogInterface, int i) {
                String   editText =infoEditDialog.getFirstEditString();
                Toast.makeText(MainActivity.this,editText,Toast.LENGTH_SHORT).show();
            }
        });

之后会设置两个button的OnClickListener。这里设置的OnClickListener是View.OnClickListener这个接口。这里其实只是写个过程,但这一步的代码,其实和之前设置id都是放在一起的。

btn_positive.setOnClickListener(mViewClickListener);
btn_negavite.setOnClickListener(mViewClickListener);

这个mViewClickListener是我们的一个对象。这个实现的是 View.OnClickListener接口,dismiss函数就是说点击这个button可以退出dialog。在这个接口对象中我们判断究竟是哪个button,并在该button的点击事件中调用最先定义的两个DialogInterface.OnClickListener对象的Onclick函数。

 private View.OnClickListener mViewClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {

            if (v == btn_positive) {
                /*
                if (mIsAutoDismiss)
                    dismiss();*/
                dismiss();
                if (mPositiveListener != null)
                    mPositiveListener.onClick(InfoEditDialog.this, DialogInterface.BUTTON_POSITIVE);
            } else if (v == btn_negavite) {
                dismiss();
                if (mNegativeListener != null)
                    mNegativeListener.onClick(InfoEditDialog.this, DialogInterface.BUTTON_NEGATIVE);
            }
        }
    };

在稍微写一下获取两个EditText的方法。

public  String getFirstEditString()
    {
        String firstEditString = edit_bank_card.getText().toString();
        if (!("".equals(firstEditString))&&firstEditString.length()>0)
            return  firstEditString;
        else
            return "你啥都没写返回尼玛阿";
    }
    public  String getSecondEditString()
    {
        String secondEditString = edit_id_card.getText().toString();
       // if (secondEditString!=null)
        return  secondEditString;
    }

之后另一个需要注意的就是要创建一个内部类Builder,这是一种设计模式。这里先把我的Builder代码放出来。

public static class Builder{
        protected Context mContext;
        CharSequence title,firstEditText,secondEditText;

        CharSequence positiveButtonText, negativeButtonText;
        DialogInterface.OnClickListener positiveButtonListener, negativeButtonListener;
        InfoEditDialog dialog;
        boolean cancelable = true;
        boolean cancelableTouchOutside = true;
        OnCancelListener onCancelListener;
        OnKeyListener onKeyListener;

        View customView;

        public Builder(Context context){mContext=context;}

        public Builder setTitle(int titleId) {
            title = mContext.getText(titleId);
            return this;
        }


        public Builder setTitle(CharSequence title) {
            this.title = title;
            return this;
        }

        public Builder setFirstEditText(CharSequence firstEditText) {
            this.firstEditText = firstEditText;
            return this;
        }
        public Builder setFirstEditTexr(int rid){
            this.firstEditText = mContext.getText(rid);
            return this;
        }
        public Builder setSecondEditText(CharSequence secondEditText) {
            this.secondEditText = secondEditText;
            return this;
        }
        public Builder setSecondEditText(int rid){
            this.secondEditText = mContext.getText(rid);
            return this;
        }
        public Builder setPositiveButton(CharSequence text,DialogInterface.OnClickListener listener)
        {
            this.positiveButtonText = text;
            this.positiveButtonListener = listener;
            return this;
        }
        public Builder setNegativeButton(CharSequence text,DialogInterface.OnClickListener listener){
            this.negativeButtonText = text;
            this.negativeButtonListener = listener;
            return this;
        }
        public Builder setCustomView(View customView) {
            this.customView = customView;
            return this;
        }
        public Builder setCancelable(boolean cancelable) {
            this.cancelable = cancelable;
            return this;
        }
        public Builder setCancelableTouchOutside(boolean cancelableTouchOutside){
            this.cancelableTouchOutside = cancelableTouchOutside;
            return this;
        }
        public Builder setOnCancelListener(OnCancelListener onCancelListener) {
            this.onCancelListener = onCancelListener;
            return this;
        }

        public Builder setOnKeyListener(OnKeyListener onKeyListener) {
            this.onKeyListener = onKeyListener;
            return this;
        }

        public  String getFirstEditText() {

            return dialog.getFirstEditString();
        }
        public String getSecondEditText(){
            return dialog.getSecondEditString();
        }
        public InfoEditDialog create(){
            final InfoEditDialog d = new InfoEditDialog(mContext);
            d.setTitle(title);

            //这里可以不设置listener
            if (positiveButtonText!=null)
                d.setPositiveButton(positiveButtonText,positiveButtonListener);
            if (negativeButtonText!=null)
                d.setNegaviteButton(negativeButtonText,negativeButtonListener);
            if (firstEditText!=null)
                d.setFirstEditText(firstEditText);
            if (secondEditText!=null)
                d.setSecondEdit(secondEditText);
            d.setCancelable(cancelable);
            d.setOnCancelListener(onCancelListener);
            d.setCanceledOnTouchOutside(cancelableTouchOutside);

            if (onKeyListener!=null)
            {
                d.setOnKeyListener(onKeyListener);
            }
            return d;
        }
        public InfoEditDialog show(){
            dialog = create();
            dialog.show();
            return dialog;
        }
        public void dismiss()
        {
            dialog.dismiss();
        }
    }

我在Activity是这样调用的。

 public void showInfoEditDialogInBuilder() {
        final InfoEditDialog.Builder builder = new InfoEditDialog.Builder(this);
        builder.setTitle("填写信息")
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        String editText = builder.getFirstEditText();
                        Toast.makeText(MainActivity.this, editText, Toast.LENGTH_SHORT).show();
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialogInterface, int i) {
                        Toast.makeText(MainActivity.this, "点击了取消", Toast.LENGTH_SHORT).show();

                    }
                })
                .setFirstEditText("请输入您的银行卡号")
                .setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        //关闭Dialog
                        builder.dismiss();
                        // 关闭当前 Activity
                        finish();
                    }
                })
                .show();
    }

效果图:
在这里插入图片描述

4 最后写一下注意事项。

1.点击其他位置不会退出Dialog(点击左下角的回退三角会退出)

dialog.setCancelableTouchOutside(false)

2.点击所有位置都不会退出Dialog(点击左下角的回退三角也不会退出)

dialog.setCancelable(false);

3.取消dialog的同时将activity注销。

效果图:
在这里插入图片描述

 dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
                    @Override
                    public void onCancel(DialogInterface dialogInterface) {
                        //关闭Dialog
                        builder.dismiss();
                        // 关闭当前 Activity
                        finish();
                    }
                })
发布了55 篇原创文章 · 获赞 28 · 访问量 9260

猜你喜欢

转载自blog.csdn.net/weixin_41796401/article/details/96636408