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

2019-09-04 11:06:25 浏览数 (1)

前言

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

简介

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

Dialog继承关系:

代码语言:javascript复制
java.lang.Object
  ↳android.app.Dialog

Android系统自带的 Dialog有四种:

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

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

- DatePickerDialog 日期对话框

- TimePickerDialog 时间对话框

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

普通弹框
代码语言:javascript复制
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();
}
选择菜单样式弹框
代码语言:javascript复制
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();
}
单选按钮样式的弹框
代码语言:javascript复制
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();
}
多选按钮样式的弹框
代码语言:javascript复制
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();
}
圆形进度弹框
代码语言:javascript复制
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();
}
水平进度弹框
代码语言:javascript复制
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();
}
选择时间弹框
代码语言:javascript复制
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();
}
选择日期弹框
代码语言:javascript复制
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自定义布局

代码语言:javascript复制
<?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中,在按钮点击事件中获取用户名和密码

代码语言:javascript复制
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布局

代码语言:javascript复制
<?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弹框代码

代码语言:javascript复制
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");
            }
        });
    }

}

运行效果

0 人点赞