アプリに選択ツールを追加する

Compose の方法を試す
Jetpack Compose は、Android で推奨される UI ツールキットです。Compose でコンポーネントを追加する方法について説明します。

Android には、ユーザーが時刻または日付を選択するためのコントロールが、すぐに使えるダイアログとして用意されています。これらの選択ツールには、時刻の要素(時、分、午前/午後)または日付の要素(月、日、年)を選択するコントロールが用意されています。

material.io の時刻選択ツールの例
図 1. モバイルのカレンダー選択ツールでの時間の選択。

これらの選択ツールを使用すると、有効かつ正しい形式で、ユーザーの言語 / 地域に合わせた時刻または日付を選択できます。

material.io のモーダル日付選択ツールの例
図 2. モーダル 日付選択ツール。

DialogFragment を使用して、各時刻または日付選択ツールをホストすることをおすすめします。DialogFragment はダイアログのライフサイクルを管理し、ハンドセットの基本ダイアログ内や大画面のレイアウトの埋め込み部分など、さまざまなレイアウト構成で選択ツールを表示できます。

時刻選択ツールを作成する

DialogFragment を使用して TimePickerDialog を表示するには、DialogFragment を拡張し、フラグメントの onCreateDialog() メソッドから TimePickerDialog を返すフラグメント クラスを定義します。

時間選択ツールの DialogFragment を拡張する

TimePickerDialogDialogFragment を定義する手順は次のとおりです。

  • TimePickerDialog のインスタンスを返す onCreateDialog() メソッドを定義します。
  • ユーザーが時刻を設定したときにコールバックを受け取るように 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 クラスをご覧ください。

これで、このフラグメントのインスタンスをアクティビティに追加するイベントのみが必要です。

時刻選択ツールを表示します

上記の例のような 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 を拡張する

DatePickerDialogDialogFragment を定義するには、次の操作を行います。

  • DatePickerDialog のインスタンスを返す onCreateDialog() メソッドを定義します。
  • 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 クラスをご覧ください。

必要なのは、このフラグメントのインスタンスをアクティビティに追加するイベントだけです。

日付選択ツールを表示する

上記の例のように 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. AUTOFILL_TYPE_DATE を返す getAutofillType() メソッドを実装します。
  3. ミリ秒単位の日付を表す AutofillValue オブジェクトを返す getAutofillValue() メソッドを実装します。戻り値オブジェクトを作成するには、forDate() メソッドを使用して AutofillValue オブジェクトを生成します。
  4. autofill() メソッドを実装します。このメソッドは、AUTOFILL_TYPE_DATE 型の AutofillValue パラメータを処理するロジックを提供します。パラメータを処理するには、パラメータの適切な文字列表現(mm/yyyy など)を作成します。文字列表現を使用して、ビューの text プロパティを設定します。
  5. ユーザーが EditText のカスタム サブクラスで日付を編集するときに選択ツールを表示する機能を実装します。ビューは、ユーザーが選択ツールで選択した値の文字列表現で text プロパティを更新します。

AUTOFILL_TYPE_DATE 値を処理する EditText のサブクラスの例については、Java または Kotlin の自動入力フレームワーク サンプルをご覧ください。

カスタムビューの自動入力サポートの詳細については、自動入力フレームワークをご覧ください。