手记

错误操作怎么办?用他让你不再害怕!—Dialog最详解

前言

Hi,好久不见,甚是想念各位花粉,为了感谢花粉们长久以来的支持,本篇文章继续分享Android中非常实用的干货—Dialog(对话框)!那么什么叫Dialog,简单来说就是一句话:弹出一个窗口,提示用户自己去选择。Dialog对话框是Android常用的基础视图组件之一,本期总结了对话框常用的几种样式,以及自定义视图和带动画效果的对话框,打开你们的IDE,赶紧跟着我们继续奋斗吧!

简介

Dialog组件并非继承自View,而是继承自ObjectDialog的生命周期通常会由Activity来控制,当Activity被销毁后,如果再有对Dialog的操作会导致异常:java.lang.IllegalArgumentException: View not attached to window manager。

Dialog继承关系:

java.lang.Object
  ↳android.app.Dialog

Android系统自带的Dialog有四种:

-AlertDialog 普通提示对话框,可以有0-3个按钮,可以有单选或者复选框的对话框,可以创建大多数界面

-ProgressDialog 进度条对话框,显示一个进度或者进度条,继承自AlertDialog

-DatePickerDialog 日期对话框

-TimePickerDialog 时间对话框

所有对话框,都是直接或简介继承自Dialog,其它的几个类均继承自AlertDialog

普通弹框
public void showDialog(View v) {
        // 这里的属性可以一直设置,因为每次设置后返回的是一个builder对象
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
 
        // 设置提示框的标题
        builder.setTitle("提示标题");
        // 设置要显示的信息
        setMessage("你妈喊你回家吃饭了!");
        // 设置确定按钮
        setPositiveButton("确定", new OnClickListener() {
             @Override
             public void onClick(DialogInterface dialog, int which) {
                  //do something
             }
        });
        setNeutralButton("取消", new OnClickListener() {
         @Override
         public void onClick(DialogInterface dialog, int which) {
            dialog.dismiss();
         }
         });
        //生成对话框
        AlertDialog alertDialog = builder.create();
        alertDialog.show();
}
选择菜单样式弹框
String[] array = new String[] {"身高160cm的妹子", "身高165cm的妹子", "身高170cm的妹子", "身高175cm的妹子"};
public void showMenuDialog(View v) {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("选择你最喜欢的妹子").
    setItems(array, new OnClickListener() {
          @Override
          public void onClick(DialogInterface dialog, int which) {
              Toast.makeText(MainActivity.this, "我喜欢" + array[which],0).show();
           }
     }).
     create().show();
}
单选按钮样式的弹框
String[] array = new String[] { "身高160cm的妹子", "身高165cm的妹子", "身高170cm的妹子", "身高175cm的妹子" };
public void radioListDialog(View v) {
        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("选择你最喜欢的妹子").
        setSingleChoiceItems(array, 0, new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, "我喜欢" + array[which],0).show();
            }
        });
        setPositiveButton("确定", new OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                Toast.makeText(MainActivity.this, "选择确定", 0).show();
            }
        });
        setNegativeButton("取消", null);
        create().show();
}
多选按钮样式的弹框
public void checkboxListDialog(View v) {
    boolean[] checkedItems = { true, false, false, true };
    final List<String> list = new ArrayList<String>();
    list.add("听音乐");
    list.add("看书");
    list.add("睡觉");
    list.add("打豆豆");
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setTitle("周末你一般都喜欢做什么").
      setMultiChoiceItems(array, checkedItems,
                          new OnMultiChoiceClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog,
                                                int which, boolean isChecked) {
                              if (isChecked) {
                                // 添加数据
                                list.add(array[which]);
                              } else {
                                list.remove(array[which]);
                              }

                            }
                          });
      setPositiveButton("确定", new OnClickListener() {
        @Override
        public void onClick(DialogInterface dialog, int which) {
          Toast.makeText(MainActivity.this, "你喜欢" + list, 0)
            .show();
        }
      });
      setNegativeButton("取消", null);
      create().show();
}
圆形进度弹框
public void circleProgress(View v) {
    //创建进度条的对话框
    ProgressDialog dialog = new ProgressDialog(this);
    //设置进度条的样式,选择圆形或条状
    dialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
    //设置标题
    dialog.setTitle("升级更新");
    //设置文本信息
    dialog.setMessage("正在下载...");
    //设置是否能用后退键出对话框,选择false就代表不能退出
    dialog.setCancelable(false);
    // 显示对话框
    dialog.show();
}
水平进度弹框
public void showProgress(View v) {
    final ProgressDialog dialog = new ProgressDialog(this);
    dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
    dialog.setMax(100);
    dialog.setTitle("升级更新");
    dialog.setMessage("正在下载...");
    dialog.setCancelable(false);
    // 显示对话框
    dialog.show();
    // 这里新建一个线程来,更新进度和关闭页面
    new Thread(new Runnable() {
      @Override
      public void run() {
        // 获取进度值的当前的值
        int index = 0;
        // 更新进度
        while (index < dialog.getMax()) {
          index++;
          try {
            Thread.sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          // 设置进度的值
          dialog.setProgress(index);

        }
        // 完成任务后,退出对话框
        dialog.cancel();
      }
    }).start();
}
选择时间弹框
public void selectTime(View v) {
        //第一个参数是上下文
        //第二个参数是监听时间选择后的事件
        //后面两个数是默认是时间
        //后一个是代表是否显示时间的格式是24小时制的
        TimePickerDialog dialog = new TimePickerDialog(this,
                new OnTimeSetListener() {
                    @Override
                    public void onTimeSet(TimePicker view, int hourOfDay,
                            int minute) {
                        Toast.makeText(MainActivity.this,
                                hourOfDay + "时" + minute + "分", 0).show();
                    }
                }, 12, 12, true);
        //显示标题
        dialog.setTitle("选择你要设定的时间");
        // 显示时间的对话框
        dialog.show();
}
选择日期弹框
 public void selectDate(View v) {
        // 第一个参数是上下文
        // 第二个参数是监听时间选择后的事件
        // 后面三个数是默认是日期数
        DatePickerDialog dialog = new DatePickerDialog(this,
                new OnDateSetListener() {
                    // 日期选择器上的月份是从0开始的
                    @Override
                    public void onDateSet(DatePicker view, int year,
                            int monthOfYear, int dayOfMonth) {
                        Toast.makeText(
                                MainActivity.this,
                                year + "年" + (monthOfYear + 1) + "月"
                                        + dayOfMonth + "日", 0).show();
                    }
                }, 2019, 9, 1);
        // 显示时间的对话框
        dialog.show();
}
自定义布局弹框

可以通过创建一个自定义布局,然后调用AlertDialog.Builder对象上的setView()方法将其添加到AlertDialog

xml自定义布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="300dp"
    android:layout_height="wrap_content"
    android:background="#0000"
    android:orientation="vertical">

    <RelativeLayout
        android:layout_width="300dp"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:background="#fff">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true"
            android:orientation="vertical"
            android:paddingLeft="20dp"
            android:paddingRight="20dp"
            android:paddingBottom="20dp">

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center_horizontal"
                android:layout_marginTop="30dp"
                android:text="开启新世界"
                android:textSize="18sp" />

            <EditText
                android:id="@+id/login_et1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="40dp"
                android:background="@null"
                android:hint="请输入用户名"
                android:textSize="16sp" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:layout_marginTop="5dp"
                android:background="#d3d3d3" />

            <EditText
                android:id="@+id/login_et2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="30dp"
                android:background="@null"
                android:hint="请输入密码"
                android:inputType="textPassword"
                android:textSize="16sp" />

            <View
                android:layout_width="match_parent"
                android:layout_height="1px"
                android:layout_marginTop="5dp"
                android:background="#d3d3d3" />

            <Button
                android:id="@+id/login_btn"
                android:layout_width="match_parent"
                android:layout_height="40dp"
                android:layout_marginTop="35dp"
                android:background="#000000"
                android:padding="5dp"
                android:text="登 录"
                android:textColor="#ffffff"
                android:textSize="16sp" />

        </LinearLayout>

    </RelativeLayout>

</LinearLayout>

DialogFragmentonCreateDialog()方法中加载自定义布局文件,并添加到AlertDialog.Builder中,在按钮点击事件中获取用户名和密码

public class LoginDialogFragment extends DialogFragment implements View.OnClickListener {

    public static final String USERNAME = "userName";
    public static final String USERPASSWORD = "userPassword";
    private EditText mUsername;
    private EditText mPassword;
    private Button loginBtn;
    private AlertDialog.Builder builder = null;

    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //设置背景透明
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        builder = new AlertDialog.Builder(getActivity());
        View view = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_login, null);
        mUsername = view.findViewById(R.id.login_et1);
        loginBtn = view.findViewById(R.id.login_btn);
        mPassword = view.findViewById(R.id.login_et2);
        loginBtn.setOnClickListener(this);
        builder.setView(view);
        return builder.create();
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.login_btn:
                if (TextUtils.isEmpty(mUsername.getText().toString()) 
                    || TextUtils.isEmpty(mPassword.getText().toString())) {
                    Toast.makeText(getActivity(), 
                                   "用户名或密码不能为空", Toast.LENGTH_SHORT).show();
                    return;
                }
                Toast.makeText(getActivity(),
                "用户名: " + mUsername.getText().toString() 
                + "   密码: " + mPassword.getText().toString(),Toast.LENGTH_SHORT).show();
                break;
        }
    }
}

MainActivity中拉起Dialog的按钮

xml布局

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center">

    <Button
        android:id="@+id/login_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="点击登录" />

</RelativeLayout>

MainActivity拉起Dialog弹框代码

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button loginBtn = (Button) findViewById(R.id.login_btn);
        loginBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                LoginDialogFragment fragment = new LoginDialogFragment();
                fragment.show(getFragmentManager(), "login");
            }
        });
    }

}

运行效果

结语

看完本篇文章以后,部分花粉肯定是属于蒙圈的状态,这是啥?连个效果图都没有,让我看啥呢。这其实是我们本期的一个特殊安排,因为我们最想看到的是各位花粉通过我们分享的技术知识快速成长起来,一起加入到Android开发这个大家庭,代码已经有啦,就看你自己啦!
欢迎关注WXGZH:下码看花。

0人推荐
随时随地看视频
慕课网APP