向应用添加选择器

试试 Compose 方式
Jetpack Compose 是推荐在 Android 设备上使用的界面工具包。了解如何在 Compose 中添加组件。

Android 以可直接使用的对话框形式提供可供用户选择时间或日期的控件。这些选择器提供了一些控件,以用于选择时间的各个部分(小时、分钟、上午/下午)或日期的各个部分(月、日、年)。

Material.io 中的时间选择器示例
图 1.在移动设备日历选择器中选择时段。

使用这些选择器有助于确保用户可以选择格式正确且已根据用户所在的语言区域进行调整的有效时间或日期。

Material.io 中的模态日期选择器示例
图 2. 模态日期选择器。

建议您使用 DialogFragment 托管每个时间或日期选择器。DialogFragment 负责管理对话框生命周期,并可让您以不同的布局配置显示选择器,例如在手机上显示为基本对话框,或在大屏幕上显示为布局的嵌入部分。

创建时间选择器

如需使用 DialogFragment 显示 TimePickerDialog,请定义一个扩展 DialogFragment 的 fragment 类,并从 fragment 的 onCreateDialog() 方法返回 TimePickerDialog

扩展时间选择器的 DialogFragment

如需为 TimePickerDialog 定义 DialogFragment,请执行以下操作:

示例如下:

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 类。

现在,您只需要一个可将此 fragment 的实例添加到 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 的实例,以及 fragment 的唯一标记名称。

创建日期选择器

创建 DatePickerDialog 与创建 TimePickerDialog 类似。区别在于您为 fragment 创建的对话框。

如需使用 DialogFragment 显示 DatePickerDialog,请定义一个用于扩展 DialogFragment 的 fragment 类,并从该 fragment 的 onCreateDialog() 方法返回 DatePickerDialog

扩展日期选择器的 DialogFragment

如需为 DatePickerDialog 定义 DialogFragment,请执行以下操作:

示例如下:

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 类。

您只需要一个可将此 fragment 的实例添加到您的 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 的实例和 Fragment 的专属标记名称。

使用具有自动填充功能的选择器

2017 年,Android 引入了自动填充框架,以便用户保存数据,方便以后用于在不同应用中填充表单。选择器提供了一个界面,可让用户更改日期或时间数据存储字段中的值,因此在自动填充情境中可能会非常有用。例如,在信用卡表单中,日期选择器可让用户输入或更改其信用卡的失效日期。

由于选择器是对话框,因此它们不会与其他字段一起显示在 Activity 中。如需在选择器不可见时显示选择器数据,您可以使用其他视图,例如 EditText,它可在选择器不可见时显示相应值。

EditText 对象本身需要 AUTOFILL_TYPE_TEXT 类型的自动填充数据。相反,自动填充服务会将数据保存为 AUTOFILL_TYPE_DATE,以便为其创建适合的表示形式。为解决类型不一致的问题,建议您创建一个继承自 EditText 的自定义视图,并实现正确处理 AUTOFILL_TYPE_DATE 类型的值所需的方法。

按照以下步骤创建可以处理 AUTOFILL_TYPE_DATE 类型值的 EditText 子类:

  1. 创建一个继承自 EditText 的类。
  2. 实现 getAutofillType() 方法,该方法会返回 AUTOFILL_TYPE_DATE
  3. 实现 getAutofillValue() 方法,该方法会返回表示日期(以毫秒为单位)的 AutofillValue 对象。如需创建返回对象,请使用 forDate() 方法生成 AutofillValue 对象。
  4. 实现 autofill() 方法。此方法提供了用于处理 AutofillValue 参数(类型为 AUTOFILL_TYPE_DATE)的逻辑。如需处理该参数,请为其创建适当的字符串表示形式,如 mm/yyyy。使用字符串表示形式来设置视图的 text 属性。
  5. 实现以下功能:当用户想要在 EditText 的自定义子类中修改日期时,显示选择器。该视图会根据用户在选择器中选择的值的字符串表示形式来更新 text 属性。

如需查看 EditText 的可处理 AUTOFILL_TYPE_DATE 值的子类示例,请参阅 JavaKotlin 中的自动填充框架示例。

如需详细了解如何为自定义视图提供自动填充支持,请参阅自动填充框架