Dodaj selektory do swojej aplikacji

Wypróbuj Compose
Jetpack Compose to zalecany zestaw narzędzi do tworzenia interfejsu użytkownika na Androidzie. Dowiedz się, jak dodawać komponenty w Compose.

Android udostępnia użytkownikom gotowe do użycia okna dialogowe, które pozwalają wybrać godzinę lub datę. Te selektory umożliwiają wybieranie poszczególnych części godziny (godzina, minuta, AM/PM) lub daty (miesiąc, dzień, rok).

Przykład selektora czasu z material.io
Rysunek 1. Wybór godziny w selektorze kalendarza na urządzeniu mobilnym.

Korzystanie z tych selektorów pomaga zapewnić, że użytkownicy mogą wybrać prawidłową datę lub godzinę, która jest poprawnie sformatowana i dostosowana do ustawień regionalnych użytkownika.

Przykład modalnego selektora daty z material.io
Rysunek 2. Modalny selektor daty.

Zalecamy używanie DialogFragment do hostowania każdego selektora czasu lub daty. DialogFragment zarządza cyklem życia okna dialogowego i umożliwia wyświetlanie selektorów w różnych konfiguracjach układu, np. w podstawowym oknie dialogowym na telefonach lub jako wbudowaną część układu na dużych ekranach.

Tworzenie selektora czasu

Aby wyświetlić TimePickerDialog za pomocą DialogFragment, zdefiniuj klasę fragmentu, która rozszerza DialogFragment i zwróć TimePickerDialog z metody onCreateDialog() fragmentu.

Rozszerzanie DialogFragment na potrzeby selektora czasu

Aby zdefiniować DialogFragment dla TimePickerDialog, wykonaj te czynności:

  • Zdefiniuj metodę onCreateDialog(), aby zwracała instancję TimePickerDialog.
  • Zaimplementuj interfejs TimePickerDialog.OnTimeSetListener , aby otrzymywać wywołanie zwrotne, gdy użytkownik ustawi godzinę.

Oto przykład:

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.
    }
}

Informacje o argumentach konstruktora znajdziesz w klasie TimePickerDialog.

Teraz potrzebujesz tylko zdarzenia, które doda instancję tego fragmentu do Twojej aktywności.

Wyświetlanie selektora czasu

Po zdefiniowaniu DialogFragment podobnego do tego w poprzednim przykładzie możesz wyświetlić selektor czasu, tworząc instancję DialogFragment i wywołując metodę show().

Oto na przykład przycisk, który po kliknięciu wywołuje metodę wyświetlającą okno dialogowe:

<Button
    android:id="@+id/pickTime"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Pick time" />

Gdy użytkownik kliknie ten przycisk, system wywoła tę metodę:

Kotlin

findViewById<Button>(R.id.pickTime).setOnClickListener {
    TimePickerFragment().show(supportFragmentManager, "timePicker")
}

Java

findViewById<Button>(R.id.pickTime).setOnClickListener {
    TimePickerFragment().show(supportFragmentManager, "timePicker");
}

Ta metoda wywołuje show() w nowej instancji DialogFragment zdefiniowanej w poprzednim przykładzie. Metoda show() wymaga instancji FragmentManager i unikalnej nazwy tagu fragmentu.

Tworzenie selektora daty

Tworzenie DatePickerDialog jest podobne do tworzenia TimePickerDialog. Różnica polega na oknie dialogowym, które tworzysz dla fragmentu.

Aby wyświetlić DatePickerDialog za pomocą DialogFragment, zdefiniuj klasę fragmentu, która rozszerza DialogFragment, i zwróć DatePickerDialog z metody onCreateDialog() fragmentu.

Rozszerzanie DialogFragment na potrzeby selektora daty

Aby zdefiniować DialogFragment dla DatePickerDialog, wykonaj te czynności:

  • Zdefiniuj metodę onCreateDialog(), aby zwracała instancję DatePickerDialog.
  • Zaimplementuj interfejs DatePickerDialog.OnDateSetListener , aby otrzymywać wywołanie zwrotne, gdy użytkownik ustawi datę.

Oto przykład:

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.
    }
}

Informacje o argumentach konstruktora znajdziesz w klasie DatePickerDialog.

Potrzebujesz tylko zdarzenia, które doda instancję tego fragmentu do Twojej aktywności.

Wyświetlanie selektora daty

Po zdefiniowaniu DialogFragment podobnego do tego w poprzednim przykładzie możesz wyświetlić selektor daty, tworząc instancję DialogFragment i wywołując metodę show().

Oto na przykład przycisk, który po kliknięciu wywołuje metodę wyświetlającą okno dialogowe:

<Button
    android:id="@+id/pickDate"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Pick date"/>

Gdy użytkownik kliknie ten przycisk, system wywoła tę metodę:

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");
}

Ta metoda wywołuje show() w nowej instancji DialogFragment zdefiniowanej w poprzednim przykładzie. Metoda show() wymaga instancji FragmentManager i unikalnej nazwy tagu fragmentu.

Używanie selektorów z autouzupełnianiem

W 2017 roku Android wprowadził platformę autouzupełniania, która umożliwia użytkownikom zapisywanie danych, które można wykorzystać do wypełniania formularzy w różnych aplikacjach. Selektory mogą być przydatne w scenariuszach autouzupełniania, ponieważ udostępniają interfejs użytkownika, który pozwala użytkownikom zmieniać wartość pola przechowującego dane daty lub godziny. Na przykład w formularzu karty kredytowej selektor daty umożliwia użytkownikom wprowadzanie lub zmianę daty ważności karty kredytowej.

Selektory są oknami dialogowymi, więc nie są wyświetlane w aktywności razem z innymi polami. Aby wyświetlać dane selektora, gdy nie jest on widoczny, możesz użyć innego widoku, np. EditText, który może wyświetlać wartość, gdy selektor jest niewidoczny.

Obiekt EditText natywnie oczekuje danych autouzupełniania typu AUTOFILL_TYPE_TEXT. Z kolei usługi autouzupełniania zapisują dane jako AUTOFILL_TYPE_DATE, aby utworzyć ich odpowiednią reprezentację. Aby rozwiązać problem z niespójnością typów, zalecamy utworzenie niestandardowego widoku, który dziedziczy po EditText i implementuje metody wymagane do prawidłowego obsługiwania wartości typu AUTOFILL_TYPE_DATE.

Aby utworzyć podklasę EditText, która może obsługiwać wartości typu AUTOFILL_TYPE_DATE:

  1. Utwórz klasę, która dziedziczy po EditText.
  2. Zaimplementuj metodę, która zwraca AUTOFILL_TYPE_DATE.getAutofillType()
  3. Zaimplementuj metodę getAutofillValue(), która zwraca obiekt AutofillValue reprezentujący datę w milisekundach. Aby utworzyć obiekt zwracany, użyj metody forDate() do wygenerowania obiektu AutofillValue.
  4. Zaimplementuj metodę autofill(). Ta metoda zawiera logikę obsługi parametru AutofillValue, który jest typu AUTOFILL_TYPE_DATE. Aby obsłużyć parametr, utwórz jego odpowiednią reprezentację w postaci ciągu znaków, np. mm/yyyy. Użyj reprezentacji w postaci ciągu znaków, aby ustawić właściwość text widoku.
  5. Zaimplementuj funkcję, która wyświetla selektor, gdy użytkownik chce edytować datę w niestandardowej podklasie EditText. Widok aktualizuje właściwość text za pomocą reprezentacji w postaci ciągu znaków wartości wybranej przez użytkownika w selektorze.

Przykład podklasy EditText, która obsługuje AUTOFILL_TYPE_DATE wartości, znajdziesz w przykładzie platformy autouzupełniania w Javie lub Kotlinie.

Więcej informacji o zapewnianiu obsługi autouzupełniania w widokach niestandardowych znajdziesz w artykule Platforma autouzupełniania.