向您的应用程序添加选择器

Android 为用户提供控件,以便他们可以选择时间或日期作为现成的对话框。这些选择器提供控件,用于选择时间的每个部分(小时、分钟、上午/下午)或日期(月、日、年)。

An example of time picker from material.io
图 1. 移动日历选择器中的小时选择。

使用这些选择器有助于确保您的用户可以选择有效的时间或日期,并确保其格式正确且已根据用户的区域设置进行调整。

An example of modal date picker from material.io
图 2. 模态日期选择器。

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

创建时间选择器

要使用 DialogFragment 显示 TimePickerDialog,请定义一个扩展 DialogFragment 的片段类,并从片段的 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 类。

现在,您只需要一个将此片段的实例添加到您的活动的事件。

显示时间选择器

在定义了与前面示例类似的 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,请执行以下操作

以下是一个示例

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

您只需要一个将此片段的实例添加到您的活动的事件。

显示日期选择器

在定义了与前面示例类似的 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 推出了 自动填充框架,它允许用户保存可以用于填充不同应用程序中表单的数据。选择器可以通过提供 UI 来让用户更改存储日期或时间数据的字段的值,这在自动填充场景中很有用。例如,在信用卡表格中,日期选择器允许用户输入或更改其信用卡的有效期。

由于选择器是对话框,因此它们不会与其他字段一起在活动中显示。为了在选择器不可见时显示选择器数据,您可以使用另一个视图,例如 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 属性。

有关处理 AUTOFILL_TYPE_DATE 值的 EditText 子类的示例,请参阅 JavaKotlin 中的自动填充框架示例。

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