Android 提供了现成的对话框控件,供用户选择时间或日期。这些选取器提供了用于选择时间(时、分、上午/下午)或日期(月、日、年)各部分的控件。
使用这些选取器有助于确保用户能够选择有效、格式正确且针对用户区域设置进行了调整的时间或日期。
我们建议您使用 DialogFragment 来托管每个时间或日期选取器。DialogFragment 会为您管理对话框生命周期,并允许您在不同的布局配置中显示选取器,例如在手机上以基本对话框形式显示,或在大屏幕上作为布局的嵌入部分显示。
创建时间选取器
要使用 DialogFragment 显示 TimePickerDialog,请定义一个继承自 DialogFragment 的片段类,并从该片段的 onCreateDialog() 方法中返回一个 TimePickerDialog。
为时间选取器扩展 DialogFragment
要为 TimePickerDialog 定义 DialogFragment,请执行以下操作:
- 定义
onCreateDialog()方法以返回TimePickerDialog的实例。 - 实现
TimePickerDialog.OnTimeSetListener接口,以便在用户设置时间时接收回调。
这是一个例子
Kotlin
class TimePickerFragment : DialogFragment(), TimePickerDialog.OnTimeSetListener { override fun onCreateDialog(savedInstanceState: Bundle): Dialog { // Use the current time as the default values for the picker. val c = Calendar.getInstance() val hour = c.get(Calendar.HOUR_OF_DAY) val minute = c.get(Calendar.MINUTE) // Create a new instance of TimePickerDialog and return it. return TimePickerDialog(activity, this, hour, minute, DateFormat.is24HourFormat(activity)) } override fun onTimeSet(view: TimePicker, hourOfDay: Int, minute: Int) { // Do something with the time the user picks. } }
Java
public static class TimePickerFragment extends DialogFragment implements TimePickerDialog.OnTimeSetListener { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // Use the current time as the default values for the picker. final Calendar c = Calendar.getInstance(); int hour = c.get(Calendar.HOUR_OF_DAY); int minute = c.get(Calendar.MINUTE); // Create a new instance of TimePickerDialog and return it. return new TimePickerDialog(getActivity(), this, hour, minute, DateFormat.is24HourFormat(getActivity())); } public void onTimeSet(TimePicker view, int hourOfDay, int minute) { // Do something with the time the user picks. } }
有关构造函数参数的信息,请参阅 TimePickerDialog 类。
现在,您只需要一个事件将此片段的实例添加到您的 Activity 中即可。
显示时间选取器
在定义了像前一个示例那样的 DialogFragment 后,您可以通过创建该 DialogFragment 的实例并调用 show() 方法来显示时间选取器。
例如,下面是一个按钮,点击该按钮时会调用一个方法来显示对话框:
<Button android:id="@+id/pickTime" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Pick time" />
当用户点击此按钮时,系统会调用以下方法:
Kotlin
findViewById<Button>(R.id.pickTime).setOnClickListener { TimePickerFragment().show(supportFragmentManager, "timePicker") }
Java
findViewById<Button>(R.id.pickTime).setOnClickListener { TimePickerFragment().show(supportFragmentManager, "timePicker"); }
此方法会对前一个示例中定义的 DialogFragment 的新实例调用 show()。show() 方法需要一个 FragmentManager 实例和一个用于该片段的唯一标记名称。
创建日期选取器
创建 DatePickerDialog 的方式与创建 TimePickerDialog 类似。区别在于您为该片段创建的对话框不同。
要使用 DialogFragment 显示 DatePickerDialog,请定义一个继承自 DialogFragment 的片段类,并从该片段的 onCreateDialog() 方法中返回一个 DatePickerDialog。
为日期选取器扩展 DialogFragment
要为 DatePickerDialog 定义 DialogFragment,请执行以下操作:
- 定义
onCreateDialog()方法以返回DatePickerDialog的实例。 - 实现
DatePickerDialog.OnDateSetListener接口,以便在用户设置日期时接收回调。
这是一个例子
Kotlin
class DatePickerFragment : DialogFragment(), DatePickerDialog.OnDateSetListener { override fun onCreateDialog(savedInstanceState: Bundle): Dialog { // Use the current date as the default date in the picker. val c = Calendar.getInstance() val year = c.get(Calendar.YEAR) val month = c.get(Calendar.MONTH) val day = c.get(Calendar.DAY_OF_MONTH) // Create a new instance of DatePickerDialog and return it. return DatePickerDialog(requireContext(), this, year, month, day) } override fun onDateSet(view: DatePicker, year: Int, month: Int, day: Int) { // Do something with the date the user picks. } }
Java
public static class DatePickerFragment extends DialogFragment implements DatePickerDialog.OnDateSetListener { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { // Use the current date as the default date in the picker. final Calendar c = Calendar.getInstance(); int year = c.get(Calendar.YEAR); int month = c.get(Calendar.MONTH); int day = c.get(Calendar.DAY_OF_MONTH); // Create a new instance of DatePickerDialog and return it. return new DatePickerDialog(requireContext(), this, year, month, day); } public void onDateSet(DatePicker view, int year, int month, int day) { // Do something with the date the user picks. } }
有关构造函数参数的信息,请参阅 DatePickerDialog 类。
您只需要一个事件将此片段的实例添加到您的 Activity 中即可。
显示日期选取器
在定义了像前一个示例那样的 DialogFragment 后,您可以通过创建该 DialogFragment 的实例并调用 show() 来显示日期选取器。
例如,下面是一个按钮,点击该按钮时会调用一个方法来显示对话框:
<Button android:id="@+id/pickDate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Pick date"/>
当用户点击此按钮时,系统会调用以下方法:
Kotlin
findViewById<Button>(R.id.pickDate).setOnClickListener { val newFragment = DatePickerFragment() newFragment.show(supportFragmentManager, "datePicker") }
Java
findViewById<Button>(R.id.pickDate).setOnClickListener { val newFragment = DatePickerFragment(); newFragment.show(supportFragmentManager, "datePicker"); }
此方法会对前一个示例中定义的 DialogFragment 的新实例调用 show()。show() 方法需要一个 FragmentManager 实例和一个用于该片段的唯一标记名称。
将选取器与自动填充功能结合使用
2017 年,Android 推出了自动填充框架 (Autofill framework),允许用户保存可用于填充不同应用中表单的数据。选取器可以在自动填充场景中发挥作用,通过提供用户界面让用户更改存储日期或时间数据的字段的值。例如,在信用卡表单中,日期选取器允许用户输入或更改其信用卡的有效期。
由于选取器是对话框,因此它们不会与其他字段一起显示在 Activity 中。为了在选取器不可见时显示选取器数据,您可以使用另一个视图,例如 EditText,它可以在选取器不可见时显示该值。
EditText 对象原生期望类型为 AUTOFILL_TYPE_TEXT 的自动填充数据。相比之下,自动填充服务会将数据保存为 AUTOFILL_TYPE_DATE 以创建适当的数据表示。为了解决类型不一致的问题,我们建议您创建一个继承自 EditText 的自定义视图,并实现正确处理 AUTOFILL_TYPE_DATE 类型值所需的方法。
请按照以下步骤创建一个可以处理 AUTOFILL_TYPE_DATE 类型值的 EditText 子类:
- 创建一个继承自
EditText的类。 - 实现
getAutofillType()方法,该方法返回AUTOFILL_TYPE_DATE。 - 实现
getAutofillValue()方法,该方法返回一个表示毫秒级日期的AutofillValue对象。要创建返回值对象,请使用forDate()方法来生成AutofillValue对象。 - 实现
autofill()方法。此方法提供了处理类型为AUTOFILL_TYPE_DATE的AutofillValue参数的逻辑。要处理该参数,请创建一个适当的字符串表示形式,例如mm/yyyy。使用该字符串表示形式来设置视图的text属性。 - 实现相关功能,以便在用户想要在
EditText的自定义子类中编辑日期时显示选取器。该视图会使用用户在选取器上选择的值的字符串表示形式来更新text属性。
有关处理 AUTOFILL_TYPE_DATE 值的 EditText 子类的示例,请参阅Java 或 Kotlin 中的自动填充框架示例。
要了解有关为自定义视图提供自动填充支持的更多信息,请参阅自动填充框架。