Dialog 使用总结

DialogAndroid中对话框相关的类,起到相关提示的作用。

Dialog在Android 中主要分为以下几类:

  • AlertDialog :警告对话框(提示对话框)
  • ProgressDialog:进度对话框
  • DatePickerDialog:日期选择对话框
  • TimerPickerDialog: 时间选择对话框
  • 自定义对话框

下面将按照如上所分类,进行一一介绍。

AlertDialog

AlertDialog 的简单使用

AlertDialog 继承 Dialog,该对象对于常用的一些对话框进行了封装。

需要注意的是AlertDialog存在两种实现并对应的存在于两个不同的包,

  • Android 原生包android.app.AlertDialog。该包中的AlertDialog并没有对不同版本的系统进行适配。在不同的手机系统上会显示不同的样式。(不推荐)。
  • v7包android.support.v7.app.AlertDialog。该包中的AlertDialog是根据google 推出的Material Desgin进行设计的,并对低版本的系统进行了适配。支持系统版本到7(Android 2.1 )以上。(推荐)

下面都将使用v7版本的AlertDialog

AlertDialog的使用分为以下几步:

  1. 创建AlertDialog.Builder对象,该对象能创建AlertDialog
  2. 调用Builder对象的方法设置图标、标题、内容、按钮等。
    • setTitle():为对话框设置标题
    • setIcon ():设置图标
    • setMessage ():设置要显示的信息
    • setPositiveButton ():设置确定按钮
    • setNegativeButton (): 设置取消按钮
    • setNeutralButton ():设置中立按钮
  3. 调用Builder对象的create()方法创建AlertDialog对话框。
  4. 调用AlertDialogshow()方法来显示对话框
  5. 调用AlertDialogdimiss()方法销毁对话框。

下面就根据上面的步骤,来创建AlertDialog方法。

    public void dialog1(View view){        // 简单的AlertDialog        // 1 . 创建AlertDialog 对象        //          注意 Dialog 的Builder的创建虽然传入的是Context,其实是多态,此处必须传入Activity对象        AlertDialog.Builder builder = new AlertDialog.Builder(this);        // 2. 通过builder 设置一些常用的属性        //   设置图标        builder.setIcon(R.mipmap.ic_launcher);        // 设置标题        builder.setTitle("提示");        //设置提示消息        builder.setMessage("这是一个基础的AlertDialog");        builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                //点击确定按钮之后的回调                Toast.makeText(AlertDialogActivity.this, "确定", Toast.LENGTH_SHORT).show();            }        });        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                //点击取消按钮之后的回调            }        });        builder.setNeutralButton("中间", new DialogInterface.OnClickListener() {            @Override            public void onClick(DialogInterface dialog, int which) {                //点击中间的按钮的回调            }        });        //3 .通过Builder  的 create方法创建AlertDialog;        AlertDialog dialog = builder.create();        // 4 . 显示对话框        dialog.show();    }

看一下效果

有以下几点需要注意:

  • AlertDialogBuilder导入的都是android.support.v7.app.AlertDialog
  • 确定,取消和中间三个按钮的接口回调,点击时默认都调用了dimiss()方法,所以我们无需手动隐藏他。
  • 一般在使用中,不会使用中间那个按钮。都是两个按钮足够:取消和确定,确定在右,取消在左。分别对应两个监听setPositiveButtonsetNegativeButton。英文单词意为积极的和消极的。
  • 创建Dialog虽然需要的是Context,但必须传入Activity对象。

如果观察仔细的会发现buildersexXXX方法,返回的仍然是Builder对象。那么我们可以修改代码之后如下:

   AlertDialog dialog = new AlertDialog.Builder(this)                .setIcon(R.mipmap.ic_launcher)                .setTitle("提示")                .setMessage("这是一个基础的AlertDialog")                .setPositiveButton("确定", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        //点击确定按钮之后的回调                        Toast.makeText(AlertDialogActivity.this, "确定", Toast.LENGTH_SHORT).show();                    }                })                .setNegativeButton("取消", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        //点击取消按钮之后的回调                    }                })                .setNeutralButton("中间", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        //点击中间的按钮的回调                    }                }).create();

类似一条链式的创建Dialog对象。

继承于Dialog的一些特性

因为AlertDialog继承Dialog,所以他拥有Dialog的特性。(该特性对于所有的对话框都适用)

其中几个常用的方法:

  • setCancelable(boolean flag):当点击返回键的时候,Dialog是否消失。 true 表示点击返回键提示框消失。 false表示不消失,即点击返回无效果。
  • setCanceledOnTouchOutside (boolean cancel) 点击对话框以外的区域时,对话框是否消失。true 表示点击以外的区域消失,false表示不消失。
        // 点击返回不会取消对话框        dialog.setCancelable(false);        // 触摸对话框以外的区域不会消失        dialog.setCanceledOnTouchOutside(false);

注意:该方法是Dialog的方法,不是Builder中的方法。

具有单选功能的对话框

实现单选功能对话框有两种实现方式,通过两个方法setItemssetSingleChoiceItems

  • setItems:通过该方法实现对话框,无需点击确定,直接点击条目之后立即消失,同时调用相应的回调。
  • setSingleChoiceItems:普通的单选效果,带有圆圈,点击确定之后隐藏。

首先看一下两个的效果图:


- setItems()方法实现单选

final String[] sex = {"男","女"};        AlertDialog dialog = new AlertDialog.Builder(this)                .setItems(sex, new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        // which 表示的 点击的索引。                        Toast.makeText(AlertDialogActivity.this, sex[which], Toast.LENGTH_SHORT).show();                    }                }).create();        dialog.show();

setItems(CharSequence[] items, final OnClickListener listener): 第一个参数为显示不同数据的数组。第二个方法为选择之后的回调。

  • setSingleChoiceItems实现:
    public void choice_single(View view){        final String[] sex = {"男","女"};        AlertDialog dialog = new AlertDialog.Builder(this)                .setSingleChoiceItems(sex, 0,new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        // which 表示的 点击的索引。                        Toast.makeText(AlertDialogActivity.this, sex[which], Toast.LENGTH_SHORT).show();                        //保存状态                    }                })                .setPositiveButton("确定", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        // 确定操作                        //通过在上一个onClick方法中的回调的记录,进行对应操作。                    }                })                .create();        dialog.show();    }

setSingleChoiceItems(CharSequence[] items, int checkedItem,final OnClickListener listener): 第一个参数表示数据数组,第二个参数表示默认选中第几条,第三个参数为借口回调。

  • 两种方式实现的比较:
    • setItems方式实现无法修改,只能选择一次,选中之后对话框就会消失。
    • setSingleChoiceItems,可以设置默认的选中条目,多次选择,选中之后不会消失,直到点击确定等隐藏对话框的操作。
    • 两者选中事件的回调相同,都是在他们的参数中的回调对象进行操作。

实现多选对话框

AlertDialog.Builder中存在方法setMultiChoiceItems(CharSequence[] items, boolean[] checkedItems, DialogInterface.OnMultiChoiceClickListener listener)设置多选对话框。

  • CharSequence[] items:可选的条目的数组数据。
  • boolean[] checkedItems:默认显示的状态,与条目一一对象,false表示不选中,true表示默认选中。
  • DialogInterface.OnMultiChoiceClickListener listener:条目选择产生变化之后的回调

看一下效果:

具体代码

        final String[] like = {"足球","篮球","乒乓球","排球"};        final boolean[] check = {false,false,true,true};        AlertDialog dialog = new AlertDialog.Builder(this)                .setMultiChoiceItems(like, check, new DialogInterface.OnMultiChoiceClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which, boolean isChecked) {                        // which 数据变化的索引   isChecked 表示变化的结果                        // 根据变化修改数据                        check[which] = isChecked;                    }                })                .setPositiveButton("确定", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialog, int which) {                        // 确定操作                        //根据check 中的true 和 flase 进行处理不同结果。                        String select = "";                        for(int i = 0;iif(check[i]){                                select= select+","+like[i];                            }                        }                        Toast.makeText(AlertDialogActivity.this, "选择了"+select, Toast.LENGTH_SHORT).show();                    }                })                .create();        dialog.show();
  • setMultiChoiceItems中的OnMultiChoiceClickListener(),数据变化时回调此方法,我们需要在此方法中保存修改的数据。

ProgressDialog 进度对话框

ProgressDialog 也是继承于Dialog,但其扩展了缓冲加载提示的功能。

总共分为两种样式,一种是圆形转圈的加载,一种是水平进度条(带有加载进度)的效果。

看一下效果:

圆形加载对话框

看一下demo

  /**     * 圆形加载对话框     * @param view     */    public void progress_circle(View view){        final ProgressDialog pd  = new ProgressDialog(this);        // 进度条为水平旋转        pd.setProgressStyle(ProgressDialog.STYLE_SPINNER);        // 设置点击返回不能取消        pd.setCancelable(false);        //设置触摸对话框以外的区域不会消失        pd.setCanceledOnTouchOutside(false);        // 设置提示的title的图标,默认是没有的,如果没有设置title的话只设置Icon是不会显示图标的        pd.setIcon(R.mipmap.ic_launcher);        // 设置标题        pd.setTitle("提示");        pd.setOnDismissListener(new DialogInterface.OnDismissListener() {            @Override            public void onDismiss(DialogInterface dialog) {                // dimiss的监听            }        });        pd.setOnCancelListener(new DialogInterface.OnCancelListener() {            @Override            public void onCancel(DialogInterface dialog) {                //cancel            }        });        pd.setMessage("这是一个圆形进度条");        pd.show();        new Thread(new Runnable() {            @Override            public void run() {                try {                    Thread.sleep(5000);                    //pd.cancel();                    pd.dismiss();                } catch (InterruptedException e) {                    e.printStackTrace();                }            }        }).start();    }
  • 直接 newProgressDialog,并没有创建什么Builder类。
  • 通过设置setProgressStyleProgressDialog.STYLE_SPINNER,使其显示圆形加载效果。
  • pd.dismiss()pd.cancel()方法都能够隐藏加载对话框。
    • cancel()表示隐藏对话框,对话框并不会被销毁。会回调setOnCancelListener.
    • dismiss():销毁对话框,回调setOnDismissListener

推荐使用dismiss()方法。因为,如果调用了cancel,在activity结束时,仍要手动调用dismiss。不然,dialog如果没有销毁,则会导致内存溢出。

水平加载对话框

  /**     * 水平加载进度对话框     * @param view     */    public void progress_horizontal(View view){        final ProgressDialog pd = new ProgressDialog(this);        // 设置水平进度条        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);        // 设置点击返回不能取消        pd.setCancelable(false);        //设置触摸对话框以外的区域不会消失        pd.setCanceledOnTouchOutside(false);        // 设置提示的title的图标,默认是没有的,如果没有设置title的话只设置Icon是不会显示图标的        pd.setIcon(R.mipmap.ic_launcher);        // 设置标题        pd.setTitle("提示");        // 默认为100        pd.setMax(100);        pd.setMessage("这是一个水平进度条");        pd.show();        new Thread(new Runnable() {            @Override            public void run() {                int i = 0;                while (i < 100) {                    try {                        Thread.sleep(200);                        // 每次增加 1%                        pd.incrementProgressBy(1);                        i++;                    } catch (Exception e) {                    }                }                pd.dismiss();            }        }).start();    }

设置一个线程,通过线程没个200ms使进度值+1,最后销毁dialog

  • 设置样式:setProgressStyleProgressDialog.STYLE_HORIZONTAL
  • 设置总的进度:pd.setMax(),整形,默认为100。
  • 动态改变进度:pd.incrementProgressBy(1);,改变当前进度值,传入的参数为递增量。

DataPickerDialog 日期选择对话框

Android 提供的原生控件,使用起来比较简单,但因为其没有对不同系统做适配,所以在不同系统上显示可能不同。只做了解即可。一般都是自定义日期对话框。

效果

注意:该效果是在Android5.0和以上系统上显示的效果。具体适配会在后面提到。

使用方式

/**     * 日期选择器     * @param view     */    public void dialog_date(View view){        // 年,天,时,分都是从 1 开始  月从1 开始        // 获取系统当前时间        Calendar instance = Calendar.getInstance();        int year = instance.get(Calendar.YEAR);        int month = instance.get(Calendar.MONTH); // 该方法month 从0 开始        int day = instance.get(Calendar.DAY_OF_MONTH);        // 构造dialog        DatePickerDialog dialog = new DatePickerDialog(this,new DatePickerDialog.OnDateSetListener() {            @Override            public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {                // 获取到的month 需要+1 获取正确的月份                Toast.makeText(AlertDialogActivity.this, year+"-"+monthOfYear+"-"+dayOfMonth, Toast.LENGTH_SHORT).show();            }        },year,month,day);        dialog.show();    }

通过Calendar获取系统当前时间,并通过DatePickerDialog的构造方法传入系统当前时间和相应的数据回调。最后在显示。

DatePickerDialog()构造方法有5个参数:
- 当前Activity
- onDateSetListener():数据的回调,在点击确定是将数据作为参数回调onDateSet方法。
- year, 年
- month,注意+1和-1
- day,天

有以下几点注意:

  • 在JAVA的时间中,无论是当前的Calendar还是DataPicker,他们的年,天,时,分都是从0开始的,也就是直接获取值显示即可。而月是从0开始的,即我们需要对数据进行+1或-1操作。
    • 如果日期是2016-6-15,则传入的参数为,2016,5,15
    • 如果onDataSet回调的日期是2016,5,15。则在显示时需要对月份+1 ,即2016,6(5+1),15
  • 颜色的设置:可以看到起弹出的大部分是粉红色,我们可以自定义粉红色区域的颜色。该颜色获取的是我们对应用设置的主题中的
    

TimePicker 时间选择器

该控件的使用和DatePickerDialog的使用基本类似。

看一下效果

注意:该效果是在Android5.0和以上系统上显示的效果。具体适配会在后面提到。

 /**     * 时间选择器     * @param view     */    public void dialog_time(View view){        // 获取系统时间        Calendar instance = Calendar.getInstance();        int hour = instance.get(Calendar.HOUR_OF_DAY);        int minute = instance.get(Calendar.MINUTE);        // 时间对话框        TimePickerDialog dialog = new TimePickerDialog(this, new TimePickerDialog.OnTimeSetListener() {            @Override            public void onTimeSet(TimePicker view, int hourOfDay, int minute) {                Toast.makeText(AlertDialogActivity.this, hourOfDay+"-"+minute, Toast.LENGTH_SHORT).show();            }        },hour,minute,true);        //显示        dialog.show();    }

TimePickerDialog的有5个参数
- 当前Activity的对象
- onTimeSetListener,数据回调。
- hour:小时
- minute:分
- is24hourView: false:不使用24小时制。true:使用24小时表示。

自定义Dialog

在平常的项目中,因为系统提供的dialog无法很好的适配不同的版本(样式不同),通常自定义Dialog实现相应功能。

实现的步骤:

  • 编写自定义的布局
  • 自定义类继承Dialog并实现构造方法。
  • 设置dialog的主题。
  • 加载自定义布局
  • 使用setContentView设置到dialog中。
  • 查找相应控件并编写逻辑。

看一下效果

  • 编写自定义布局dialog_simple.xml
"http://schemas.android.com/apk/res/android"    android:orientation="vertical"    android:background="@drawable/shape_dialog_psd_bg"    android:layout_width="250dp"    android:layout_height="400dp">    "1"        android:gravity="center"        android:text="一个简单的自定义dialog"        android:layout_width="match_parent"        android:layout_height="match_parent" />    "10dp"        android:layout_gravity="right"        android:layout_width="wrap_content"        android:layout_height="wrap_content">        "@+id/dialog_simple_cancel"            android:textSize="16sp"            android:textStyle="bold"            android:text="关闭"            android:layout_width="wrap_content"            android:layout_height="wrap_content" />    
  • 很多需求模仿IOS 实现外框是一个圆角矩形的形式。Dialog并没有提供对应的方法,我们需要从自定义布局上,设置它的背景为圆角矩形。

圆角矩形shape资源shape_dialog_psd_bg.xml

"http://schemas.android.com/apk/res/android"    android:shape="rectangle">    "8dp" />    "#fff" />    "1dp"        android:color="#ececec" />

下面就是编写CustomDialog

/** * 简单的对话框 * Created by MH on 2016/6/15. */public class SimpleDialog extends Dialog implements View.OnClickListener {    public SimpleDialog(Context context) {        // 注意,在此处设置样式        super(context,R.style.CustomDialog);        // 设置我们的布局到dialog中        setContentView(R.layout.dialog_simple);        // 初始化布局        initView();    }    private void initView() {        findViewById(R.id.dialog_simple_cancel).setOnClickListener(this);    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.dialog_simple_cancel:                // 对应的点击事件                this.dismiss();                break;        }    }}

在如上类中,关键的几步如下:

  • 重写构造方法,我们选择只有一个参数的。
  • 构造方法调用父类构造方法并传入了dialog的样式。
  • setContentView()设置自定义布局到dialog中。
  • 查找控件并编写相应的逻辑

其中需要注意的一点为设置样式,该样式设置的目的是为了统一不同系统版本下显示的样式,如果不设置,在低于Android5。0的系统下会爆炸。。。

在此定义的样式一般为

 <style name="CustomDialog" parent="@android:style/Theme.Dialog">        -- 是否浮现在activity之上 -->        <item name="android:windowIsFloating">trueitem>        -- 无标题 -->        <item name="android:windowNoTitle">trueitem>        -- 背景透明 -->        <item name="android:windowBackground">@android:color/transparent    style>

自定义Dialog大概就这么多,复杂的无非就是界面复杂点,逻辑复杂点那么多。

Dialog 设置动画

看一下效果图

下面就开始实现,定义动画需要通过xml文件来编写动画

  • dialog_anim_enter.xml 进入的动画
<set xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="500">    <translate android:fromYDelta="-10%p" />    <alpha        android:fromAlpha="0"        android:interpolator="@android:anim/accelerate_interpolator"        android:toAlpha="1" />set>
  • dialog_anim_exit.xml 离开动画
<set xmlns:android="http://schemas.android.com/apk/res/android"    android:duration="500"    >    <translate android:toYDelta="60%p" />    <alpha        android:fromAlpha="1"        android:interpolator="@android:anim/accelerate_interpolator"        android:toAlpha="0" />set>

如果对动画不是太熟悉的,可以看我之前的博客Android动画之视图动画和属性动画

在这里需要注意,虽然是相对父布局,但仍然是我们显示的dialog的左上角为0坐标开始偏移的,效果是相对于本身的动画。我猜测应该是dialog外层包裹了另一个和他一样大小的布局。

  • 编写动画的样式
  <style name="DialogAnim" parent="@android:style/Animation">        <item name="android:windowEnterAnimation">@anim/dialog_anim_enter        "android:windowExitAnimation">@anim/dialog_anim_exit  style>
  • 通过dialog.getWindow().setWindowAnim(int resId)方法设置动画
/**     * dialog设置动画     */    public void dialog_anim(View view){        SimpleDialog dialog = new SimpleDialog(this);        // 设置动画        dialog.getWindow().setWindowAnimations(R.style.DialogAnim);        dialog.show();    }

该动画的设置方法对所有的dialog都适用,即之前系统提供的AlertDialog都适用。

设置Dialog的大小

两种实现方式:

  • 第一种方式 通过dialog.getWindow().setLayout(100,100); 设置大小。

  • 第二种方式 通过dialog.getWindow().getAttributes();设置。

    /**     * 设置大小     * @param view     */    public void dialog_size(View view) {        SimpleDialog dialog = new SimpleDialog(this);//        // 第一种方式//        dialog.getWindow().setLayout(100,100);        // 第二种方式  获取参数        WindowManager.LayoutParams params = dialog.getWindow().getAttributes();        // 设置高度        params.height = 100;        // 设置宽度        params.width = 100;        // 设置        dialog.getWindow().setAttributes(params);        dialog.show();    }
  • 其实第一种方式,在其内部实现上也是通过第二种方式设置的。
  • 第二种方式获取到的params ,里面包含了很多dialog的显示属性,不是只要高度和宽度。

该大小的设置方法对所有的dialog都适用,即之前系统提供的AlertDialog都适用。

该博客中的源码已经更新到github,有需要者请移步。

更多相关文章

  1. 浅谈Java中Collections.sort对List排序的两种方法
  2. Python list sort方法的具体使用
  3. python list.sort()根据多个关键字排序的方法实现
  4. android上一些方法的区别和用法的注意事项
  5. android EditText设置不可写
  6. android实现字体闪烁动画的方法
  7. android“设置”里的版本号
  8. Android中dispatchDraw分析
  9. Android四大基本组件介绍与生命周期

随机推荐

  1. 自定义AnimationDrawable动画播放完监听
  2. 地图的使用
  3. Android短信插入器源码
  4. Android学习笔记之数据持久化
  5. 使用View绘制虚线时demo,方便复习
  6. org.greenrobot.eventbus.EventBusExcept
  7. android Textview 循环滚动效果
  8. How to compile Android(安卓)on Ubuntu
  9. 自定义Dialog位置和大小
  10. android gradle plugin 和 gradle 版本对