Android 日期选取器

概述

有时用户必须将数据输入到 Android 应用程序中。 为了帮助实现此目的,Android 框架提供了 DatePicker 小组件和 DatePickerDialogDatePicker 允许用户在各种设备和应用程序中一致的界面中选择年、月和日。 DatePickerDialog 是一个帮助程序类,用于将 DatePicker 封装在对话框中。

新式 Android 应用程序应当将 DatePickerDialog 显示在 DialogFragment 中。 这将允许应用程序将 DatePicker 显示为弹出对话框或嵌入到活动中。 此外,DialogFragment 还将管理对话框的生命周期和显示,从而减少必须实现的代码量。

本指南将演示如何使用 DatePickerDialog(包装在一个 DialogFragment 中)。 当用户单击活动上的按钮时,示例应用程序将 DatePickerDialog 显示为模式对话框。 当用户设置日期时,TextView 将更新为所选的日期。

Screenshot of Pick Date button followed by Date Picker dialog

要求

本指南的示例应用程序面向 Android 4.1(API 级别 16)或更高版本,但也适用于 Android 3.0(API 级别 11 或更高版本)。 通过向项目添加 Android 支持库 v4 并更改一些代码,可以支持旧版 Android。

使用 DatePicker

此示例将扩展 DialogFragment。 子类将托管并显示一个 DatePickerDialog

Closeup of Date Picker dialog

当用户选择一个日期并单击“确定”按钮时,DatePickerDialog 将调用该方法 IOnDateSetListener.OnDateSet 此接口由宿主 DialogFragment 实现。 如果用户单击“取消”按钮,则片段和对话框将自行消失。

DialogFragment 可通过多种方式将所选日期返回到宿主活动:

  1. 调用某个方法或设置某个属性 – 活动可以提供专门用于设置此值的属性或方法。

  2. 引发某个事件 – DialogFragment 可以定义当 OnDateSet 被调用时将引发的事件。

  3. 使用 ActionDialogFragment 可以调用 Action<DateTime> 来在活动中显示日期。 活动将在实例化 DialogFragment 时提供 Action<DateTime。 此示例将使用第三种方式,并要求活动向 DialogFragment 提供 Action<DateTime>

扩展 DialogFragment

显示 DatePickerDialog 的第一步是实现子类 DialogFragment 并使其实现 IOnDateSetListener 接口:

public class DatePickerFragment : DialogFragment, 
                                  DatePickerDialog.IOnDateSetListener
{
    // TAG can be any string of your choice.
    public static readonly string TAG = "X:" + typeof (DatePickerFragment).Name.ToUpper();
    
    // Initialize this value to prevent NullReferenceExceptions.
    Action<DateTime> _dateSelectedHandler = delegate { };
    
    public static DatePickerFragment NewInstance(Action<DateTime> onDateSelected)
    {
        DatePickerFragment frag = new DatePickerFragment();
        frag._dateSelectedHandler = onDateSelected;
        return frag;
    }
    
    public override Dialog OnCreateDialog(Bundle savedInstanceState)
    {
        DateTime currently = DateTime.Now;
        DatePickerDialog dialog = new DatePickerDialog(Activity, 
                                                       this, 
                                                       currently.Year, 
                                                       currently.Month - 1,
                                                       currently.Day);
        return dialog;
    }
    
    public void OnDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth)
    {
        // Note: monthOfYear is a value between 0 and 11, not 1 and 12!
        DateTime selectedDate = new DateTime(year, monthOfYear + 1, dayOfMonth);
        Log.Debug(TAG, selectedDate.ToLongDateString());
        _dateSelectedHandler(selectedDate);
    }
}

NewInstance 方法被调用来实例化新的 DatePickerFragment。 此方法采用当用户单击 DatePickerDialog 中的“确定”按钮时将被调用的 Action<DateTime>

当要显示片段时,Android 将调用方法 OnCreateDialog。 此方法将创建一个新的 DatePickerDialog 对象,并使用当前日期和回调对象(即 DatePickerFragment 的当前实例)初始化它。

注意

请注意,当调用 IOnDateSetListener.OnDateSet 时,月份的值介于 0 到 11 之间,而不是 1 到 12 之间。 月份的日将介于 1 到 31 之间(具体取决于所选月份)。

显示 DatePickerFragment

现在已经实现了 DialogFragment,本部分将研究如何在活动中使用该片段。 在本指南附带的示例应用中,活动将使用 NewInstance 工厂方法实例化 DialogFragment,然后调用 DialogFragment.Show 来显示它。 作为实例化 DialogFragment 的一部分,活动将传递一个 Action<DateTime>,后者将在活动托管的 TextView 中显示日期:

[Activity(Label = "@string/app_name", MainLauncher = true, Icon = "@drawable/icon")]
public class MainActivity : Activity
{
    TextView _dateDisplay;
    Button _dateSelectButton;

    protected override void OnCreate(Bundle bundle)
    {
        base.OnCreate(bundle);
        SetContentView(Resource.Layout.Main);

        _dateDisplay = FindViewById<TextView>(Resource.Id.date_display);
        _dateSelectButton = FindViewById<Button>(Resource.Id.date_select_button);
        _dateSelectButton.Click += DateSelect_OnClick;
    }

    void DateSelect_OnClick(object sender, EventArgs eventArgs)
    {
        DatePickerFragment frag = DatePickerFragment.NewInstance(delegate(DateTime time)
                                                                 {
                                                                     _dateDisplay.Text = time.ToLongDateString();
                                                                 });
        frag.Show(FragmentManager, DatePickerFragment.TAG);
    }
}

总结

此示例讨论了如何将 DatePicker 小组件显示为作为 Android 活动的一部分的弹出式模式对话框。 它提供了一个示例 DialogFragment 实现并讨论了 IOnDateSetListener 接口。 此示例还演示了 DialogFragment 如何与宿主活动进行交互来显示所选日期。