本节介绍几种常用的对话框控件,包括:如何使用提醒对话框处理不同的选项,如何使用日期对话框获取用户选择的日期,如何使用时间对话框获取用户选择的时间。
3.4.1 提醒对话框AlertDialog
AlertDialog名为提醒对话框,它是Android中最常用的对话框,可以完成常见的交互操作,例如提示、确认、选择等功能。由于AlertDialog没有公开的构造方法,因此必须借助建造器AlerDialog.Builder才能完成参数设置,AlertDialog.Builder的常用方法说明如下。
● setIcon:设置对话框的标题图标。
● setTitle:设置对话框的标题文本。
● setMessage:设置对话框的内容文本。
● setPositiveButton:设置肯定按钮的信息,包括按钮文本和点击监听器。
● setNegativeButton:设置否定按钮的信息,包括按钮文本和点击监听器。
● setNeutralButton:设置中性按钮的信息,包括按钮文本和点击监听器,该方法比较少用。
通过AlertDialog.Builder设置完对话框参数,还需调用建造器的create方法才能生成对话框实例。最后调用对话框实例的show方法,在页面上弹出提醒对话框。
下面是构建并显示提醒对话框的Java代码例子:
// 创建提醒对话框的建造器
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("尊敬的用户");// 设置对话框的标题文本
builder.setMessage("你真的要卸载我吗?"); // 设置对话框的内容文本
// 设置对话框的肯定按钮文本及其点击监听器
builder.setPositiveButton("残忍卸载", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
tv_alert.setText("虽然依依不舍,但是只能离开了");
}
});
// 设置对话框的否定按钮文本及其点击监听器
builder.setNegativeButton("我再想想", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
tv_alert.setText("让我再陪你三百六十五个日夜");
}
});
AlertDialog alert = builder.create();// 根据建造器构建提醒对话框对象
alert.show();// 显示提醒对话框
提醒对话框的弹窗效果如图所示,可见该对话框有标题和内容,还有两个按钮。
点击不同的对话框会触发不同的处理逻辑。例如,图为点击 “我再想想” 按钮后的页面,
图为点击 “残忍卸载” 按钮后的页面。
完整代码如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".AlertDialogActivity">
<Button
android:id="@+id/btn_alert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="弹出提醒对话框"
android:textColor="@color/black"
android:textSize="17sp" />
<TextView
android:id="@+id/tv_alert"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:textColor="@color/black"
android:textSize="17sp" />
</LinearLayout>
package com.example.chapter05;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
public class AlertDialogActivity extends AppCompatActivity implements View.OnClickListener {
private TextView tv_alert;// 声明一个文本视图对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_alert_dialog);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
// 给btn_alert设置点击监听器,一旦用户点击按钮,就触发监听器的onClick方法
findViewById(R.id.btn_alert).setOnClickListener(this);
// 从布局文件中获取名叫tv_alert的文本视图
tv_alert = findViewById(R.id.tv_alert);
}
@Override
public void onClick(View v) {
if (v.getId()==R.id.btn_alert){
// 创建提醒对话框的建造器
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("尊敬的用户");// 设置对话框的标题文本
builder.setMessage("你真的要卸载我吗?"); // 设置对话框的内容文本
// 设置对话框的肯定按钮文本及其点击监听器
builder.setPositiveButton("残忍卸载", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
tv_alert.setText("虽然依依不舍,但是只能离开了");
}
});
// 设置对话框的否定按钮文本及其点击监听器
builder.setNegativeButton("我再想想", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
tv_alert.setText("让我再陪你三百六十五个日夜");
}
});
AlertDialog alert = builder.create();// 根据建造器构建提醒对话框对象
alert.show();// 显示提醒对话框
}
}
}
3.4.2 日期对话框 DatePickerDialog
虽然EditText提供了inputType="date"的日期输入,但是很少有人会手工输入完整日期,况且EditText还不支持“****年**月**日”这样的中文日期,所以系统提供了专门的日期选择器DatePicker,供用户选择具体的年、月、日。不过,DatePicker并非弹窗模式,而是在当前页面占据一块区域,并且不会自动关闭。按习惯来说,日期控件应该弹出对话框,选择完日期就要自动关闭对话框。因此,很少直接在界面上显示DatePicker,而是利用已经封装好的日期选择对话框DatePickerDialog。
DatePickerDialog相当于在AlertDialog上装载了DatePicker,编码时只需调用构造方法设置当前的年、月、日,然后调用show方法即可弹出日期对话框。日期选择事件则由监听器OnDateSetListener负责响应,在该监听器的onDateSet方法中,开发者获取用户选择的具体日期,再做后续处理。特别注意onDateSet的月份参数,它的起始值不是1而是0。也就是说,一月份对应的参数值为0,十二月份对应的参数值为11,中间月份的数值以此类推。
在界面上内嵌显示DatePicker的效果如图所示,其中,年、月、日通过上下滑动选择。
单独弹出日期对话框的效果如图所示,其中年、月、日按照日历风格展示。
下面是使用日期对话框的Java代码例子,包括弹出日期对话框和处理日期监听事件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".DatePickerActivity">
<Button
android:id="@+id/btn_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请选择日期"
android:textColor="@color/black"
android:textSize="17sp" />
<DatePicker
android:id="@+id/dp_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:calendarViewShown="false"
android:datePickerMode="spinner"
android:layout_gravity="center"
android:spinnersShown="true" />
<Button
android:id="@+id/btn_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="确 定"
android:textColor="@color/black"
android:textSize="17sp" />
<TextView
android:id="@+id/tv_date"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:textColor="@color/black"
android:textSize="17sp" />
</LinearLayout>
package com.example.chapter05;
import android.app.DatePickerDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.DatePicker;
import android.widget.TextView;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import java.util.Calendar;
public class DatePickerActivity extends AppCompatActivity implements View.OnClickListener, DatePickerDialog.OnDateSetListener {
private TextView tv_date; // 声明一个文本视图对象
private DatePicker dp_date; // 声明一个日期选择器对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_date_picker);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
tv_date = findViewById(R.id.tv_date);
// 从布局文件中获取名叫dp_date的日期选择器
dp_date = findViewById(R.id.dp_date);
findViewById(R.id.btn_date).setOnClickListener(this);
findViewById(R.id.btn_ok).setOnClickListener(this);
}
@Override
public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
// 获取日期对话框设定的年月份
String desc = String.format("您选择的日期是%d年%d月%d日",
year, month + 1, dayOfMonth);
tv_date.setText(desc);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_date) {
// 获取日历的一个实例,里面包含了当前的年月日
Calendar calendar = Calendar.getInstance();
// 构建一个日期对话框,该对话框已经集成了日期选择器。
// DatePickerDialog的第二个构造参数指定了日期监听器
DatePickerDialog dialog = new DatePickerDialog(this, this,
calendar.get(Calendar.YEAR), // 年份
calendar.get(Calendar.MONTH), // 月份
calendar.get(Calendar.DAY_OF_MONTH)); // 日子
dialog.show(); // 显示日期对话框
} else if (v.getId() == R.id.btn_ok) {
// 获取日期选择器dp_date设定的年月份
String desc = String.format("您选择的日期是%d年%d月%d日",
dp_date.getYear(), dp_date.getMonth() + 1, dp_date.getDayOfMonth());
tv_date.setText(desc);
}
}
}
3.4.3 时间对话框 TimePickerDialog
既然有了日期选择器,还得有对应的时间选择器。同样,在实际开发中也很少直接用TimePicker,而是用封装好的时间选择对话框TimePickerDialog。该对话框的用法类似DatePickerDialog,不同之处主要有两个:
(1)构造方法传入的是当前的小时与分钟,最后一个参数表示是否采取24小时制,一般为true表示小时的数值范围0~23;若为false则表示采取12小时制。
(2)时间选择监听器为OnTimeSetListener,对应需要实现onTimeSet方法,在该方法中可获得用户选择的小时和分钟。
在界面上内嵌显示TimePicker的效果如图所示,其中,小时与分钟可通过上下滑动选择。
单独弹出时间对话框的效果如图所示,其中小时与分钟按照钟表风格展示。
下面是使用时间对话框的Java代码例子,包括弹出时间对话框和处理时间监听事件:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:id="@+id/main"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".TimePickerActivity">
<Button
android:id="@+id/btn_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="请选择时间"
android:textColor="@color/black"
android:textSize="17sp" />
<!-- timePickerMode取值spinner表示下拉框风格,取值clock表示钟表风格 -->
<TimePicker
android:id="@+id/tp_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:calendarViewShown="false"
android:timePickerMode="spinner"
android:gravity="center"
android:spinnersShown="true" />
<Button
android:id="@+id/btn_ok"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="确 定"
android:textColor="@color/black"
android:textSize="17sp" />
<TextView
android:id="@+id/tv_time"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:textColor="@color/black"
android:textSize="17sp" />
</LinearLayout>
package com.example.chapter05;
import android.app.TimePickerDialog;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;
import android.widget.TimePicker;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import java.util.Calendar;
public class TimePickerActivity extends AppCompatActivity implements View.OnClickListener, TimePickerDialog.OnTimeSetListener {
private TextView tv_time; // 声明一个文本视图对象
private TimePicker tp_time; // 声明一个时间选择器对象
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
EdgeToEdge.enable(this);
setContentView(R.layout.activity_time_picker);
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main), (v, insets) -> {
Insets systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars());
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom);
return insets;
});
tv_time = findViewById(R.id.tv_time);
// 从布局文件中获取名叫tp_time的时间选择器
tp_time = findViewById(R.id.tp_time);
findViewById(R.id.btn_time).setOnClickListener(this);
findViewById(R.id.btn_ok).setOnClickListener(this);
}
@Override
public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
// 获取时间对话框设定的小时和分钟
String desc = String.format("您选择的时间是%d时%d分", hourOfDay, minute);
tv_time.setText(desc);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.btn_time) {
// 获取日历的一个实例,里面包含了当前的时分秒
Calendar calendar = Calendar.getInstance();
// 构建一个时间对话框,该对话框已经集成了时间选择器。
// TimePickerDialog的第二个构造参数指定了时间监听器
TimePickerDialog dialog = new TimePickerDialog(this, this,
calendar.get(Calendar.HOUR_OF_DAY), // 小时
calendar.get(Calendar.MINUTE), // 分钟
true); // true表示24小时制,false表示12小时制
dialog.show(); // 显示时间对话框
} else if (v.getId() == R.id.btn_ok) {
// 获取时间选择器tp_time设定的小时和分钟
String desc = String.format("您选择的时间是%d时%d分",
tp_time.getCurrentHour(), tp_time.getCurrentMinute());
tv_time.setText(desc);
}
}
}