一. 前言

1
2
3
//Dialog(对话框)
java.lang.Object
↳android.app.Dialog

那么什么叫Dialog,简单来说就是一句话:弹出一个窗口,提示用户自己去选择。Dialog的生命周期通常会由Activity来控制,当Activity被销毁后,如果再有对Dialog的操作会导致异常。

1
java.lang.IllegalArgumentException: View not attached to window manager。

Android系统自带的Dialog有四种:

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

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

-DatePickerDialog 日期对话框

-TimePickerDialog 时间对话框

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

二. 系统默认的弹框

1. 普通的对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
* 普通的对话框
* @param view
*/
public void showDialog(View view) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);

builder.setTitle("提示标题");
builder.setMessage("显示的信息");

builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//do something
}
});

builder.setNeutralButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});

//生成对话框
AlertDialog alertDialog = builder.create();
alertDialog.show();
}

2. 菜单按钮样式的对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 菜单按钮样式的对话框
* @param view
*/
public void showMenuDialog(View view) {
final String[] messages = {
"身高160cm的妹子",
"身高165cm的妹子",
"身高170cm的妹子",
"身高175cm的妹子"
};

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("选择你喜欢的妹子");
builder.setItems(messages, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "我喜欢"+messages[which], Toast.LENGTH_SHORT).show();
}
});

AlertDialog alertDialog = builder.create();
alertDialog.show();
}

3. 单选按钮样式的对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 单选按钮样式的对话框
* @param view
*/
public void showRadioDialog(View view) {
final String[] messages = {
"身高160cm的妹子",
"身高165cm的妹子",
"身高170cm的妹子",
"身高175cm的妹子"
};

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("选择你喜欢的妹子");
builder.setSingleChoiceItems(messages, 0, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "我喜欢"+messages[which], Toast.LENGTH_SHORT).show();
}
});

AlertDialog alertDialog = builder.create();
alertDialog.show();
}

4. 多选按钮样式的对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
* 多选按钮样式的对话框
* @param view
*/
public void showCheckBoxDialog(View view) {
final boolean[] checkedItems = {true,false,false,true};
final String[] messages = {"听音乐","看书","睡觉","打豆豆"};

AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("周末你一般都喜欢做什么");
builder.setMultiChoiceItems(messages, checkedItems, new DialogInterface.OnMultiChoiceClickListener() {
@Override
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
if (isChecked){
checkedItems[which] = true;
}else {
checkedItems[which] = false;
}
}
});

builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
StringBuilder temp = new StringBuilder();
for (int i = 0; i < checkedItems.length; i++) {
if (checkedItems[i]){
temp.append(messages[i]+" ");
}
}
Toast.makeText(MainActivity.this, "我喜欢"+temp, Toast.LENGTH_SHORT).show();
}
});

builder.setNegativeButton("取消",null);

AlertDialog alertDialog = builder.create();
alertDialog.show();
}

5. 圆形进度样式的对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 圆形进度样式的对话框
* @param view
*/
public void showCircleProgressDialog(View view) {
//创建进度条对话框
ProgressDialog progressDialog = new ProgressDialog(this);
//设置进度条的样式
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
//设置标题
progressDialog.setTitle("升级更新");
//设置文本信息
progressDialog.setMessage("正在下载...");
//设置是否能用后退键退出
progressDialog.setCancelable(false);
//显示对话框
progressDialog.show();
}

6. 水平进度样式的对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 水平进度样式的对话框
* @param view
*/
public void showProgressDialog(View view) {
//创建进度条对话框
final ProgressDialog progressDialog = new ProgressDialog(this);
//设置进度条的样式
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
//设置标题
progressDialog.setTitle("升级更新");
//设置文本信息
progressDialog.setMessage("正在下载...");
//设置是否能用后退键退出
progressDialog.setCancelable(false);
//设置最大进度
progressDialog.setMax(100);
//显示对话框
progressDialog.show();
}

7. 选择时间样式的对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* 选择时间样式的对话框
* @param view
*/
public void showSelectTimeDialog(View view) {
/**
* context:山下文
* timeSetListener:监听器
* hourOfDay:默认的时间
* minute:默认的时间
* is24HourView:是否是24小时制
*/
TimePickerDialog timePickerDialog = new TimePickerDialog(
this,
new TimePickerDialog.OnTimeSetListener() {
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
Toast.makeText(MainActivity.this, hourOfDay+"时"+minute+"分", Toast.LENGTH_SHORT).show();
}
},
12,
12,
true
);
//显示标题
timePickerDialog.setTitle("选择你要设定的时间");
//显示时间的对话框
timePickerDialog.show();
}

8. 选择日期样式的对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 选择日期样式的对话框
* @param view
*/
public void showSelectDateDialog(View view) {
//显示时间的对话框
DatePickerDialog datePickerDialog = new DatePickerDialog(
this,
new DatePickerDialog.OnDateSetListener() {
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
Toast.makeText(MainActivity.this, year+"年"+month+"月"+dayOfMonth+"日", Toast.LENGTH_SHORT).show();
}
},
2019,
9,
1
);
datePickerDialog.show();
}

三. 自定义布局的对话框

了解了dialog之后,我们还需要了解一下FragmentDialog,我们常继承它来自定义对话框。

1. 自定义步骤

① 创建你想要的对话框的布局文件

② 自定义一个继承于DialogFragment的类

③ 在继承的类中重写onCreateDialog,加载布局文件,完成相关的事件处理。

④ 在Activity中使用

2. demo

① 布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
<?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>

② 自定义的类以及加载布局处理事件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
public class LoginDialogFragment extends DialogFragment implements View.OnClickListener {
//账号
private EditText userName;
//密码
private EditText password;
//登录
private Button loginBtn;

@NonNull
@Override
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
//创建构建者
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());

//加载布局
View inflate = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_layout, null);

//找到控件
userName = inflate.findViewById(R.id.login_et1);
password = inflate.findViewById(R.id.login_et2);
loginBtn = inflate.findViewById(R.id.login_btn);
loginBtn.setOnClickListener(this);

//将布局设置给对话框
builder.setView(inflate);

return builder.create();
}

@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.login_btn:

if (TextUtils.isEmpty(userName.getText().toString())
|| TextUtils.isEmpty(password.getText().toString())){
Toast.makeText(getActivity(), "用户名或者密码不能为空", Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(getActivity(), "用户名:"+userName.getText()+"密码:"+password.getText(), Toast.LENGTH_SHORT).show();
}

break;
default:
break;
}
}
}

③ 在Activity中使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

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

</RelativeLayout>

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

findViewById(R.id.login_btn).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LoginDialogFragment loginDialogFragment = new LoginDialogFragment();
loginDialogFragment.show(getSupportFragmentManager(),"login");
}
});
}
}

④ 运行效果

四. 进阶内容

Android 中自定义 Dialog 显示隐藏动画

自定义dialog (构建者模式打造自定义dialog)

参考文章

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