前言
Hi,好久不见,甚是想念各位花粉,为了感谢花粉们长久以来的支持,本篇文章继续分享Android中非常实用的干货— Dialog
(对话框)!那么什么叫 Dialog
,简单来说就是一句话:弹出一个窗口,提示用户自己去选择。 Dialog
对话框是Android常用的基础视图组件之一,本期总结了对话框常用的几种样式,以及自定义视图和带动画效果的对话框,打开你们的IDE,赶紧跟着我们继续奋斗吧!
简介
Dialog
组件并非继承自 View
,而是继承自 Object
, Dialog
的生命周期通常会由 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
。
普通弹框
代码语言: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
自定义布局
<?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>
在 DialogFragment
的 onCreateDialog()
方法中加载自定义布局文件,并添加到 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");
}
});
}
}
运行效果