Thêm bộ chọn vào ứng dụng

Thử cách Compose
Jetpack Compose là bộ công cụ giao diện người dùng được đề xuất cho Android. Tìm hiểu cách thêm các thành phần trong Compose.

Android cung cấp các chế độ kiểm soát để người dùng chọn giờ hoặc ngày làm hộp thoại có sẵn. Các bộ chọn này cung cấp các chế độ kiểm soát để chọn từng phần của thời gian (giờ, phút, sáng/chiều) hoặc ngày (tháng, ngày, năm).

Ví dụ về bộ chọn thời gian trên material.io
Hình 1. Lựa chọn giờ trong bộ chọn lịch trên thiết bị di động.

Việc sử dụng những bộ chọn này sẽ giúp đảm bảo rằng người dùng của bạn có thể chọn ngày hoặc giờ hợp lệ, có định dạng chính xác và được điều chỉnh theo ngôn ngữ của người dùng.

Ví dụ về bộ chọn ngày phương thức từ material.io
Hình 2. Bộ chọn ngày theo phương thức thức bật.

Bạn nên sử dụng DialogFragment để lưu trữ từng bộ chọn ngày hoặc giờ. DialogFragment quản lý vòng đời hộp thoại cho bạn và cho phép bạn hiển thị bộ chọn ở nhiều cấu hình bố cục, chẳng hạn như trong hộp thoại cơ bản trên thiết bị cầm tay hoặc dưới dạng phần nhúng của bố cục trên màn hình lớn.

Tạo bộ chọn giờ

Để hiển thị TimePickerDialog bằng cách sử dụng DialogFragment, hãy xác định một lớp phân đoạn giúp mở rộng DialogFragment và trả về TimePickerDialog từ phương thức onCreateDialog() của phân đoạn.

Mở rộng DialogFragment cho bộ chọn giờ

Để xác định DialogFragment cho TimePickerDialog, hãy làm như sau:

  • Xác định phương thức onCreateDialog() để trả về một phiên bản của TimePickerDialog.
  • Triển khai giao diện TimePickerDialog.OnTimeSetListener để nhận lệnh gọi lại khi người dùng thiết lập giờ.

Ví dụ:

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

Xem lớp TimePickerDialog để biết thông tin về các đối số của hàm khởi tạo.

Bây giờ, bạn chỉ cần thêm một sự kiện, sự kiện này thêm một phiên bản của phân đoạn này vào hoạt động của bạn.

Hiện bộ chọn giờ

Sau khi xác định DialogFragment như ví dụ trước, bạn có thể hiển thị bộ chọn giờ bằng cách tạo một phiên bản của DialogFragment và gọi phương thức show().

Ví dụ: sau đây là một nút mà khi nhấn vào, hệ thống sẽ gọi một phương thức để hiện hộp thoại:

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

Khi người dùng nhấn vào nút này, hệ thống sẽ gọi phương thức sau:

Kotlin

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

Java

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

Phương thức này gọi show() trên một phiên bản mới của DialogFragment được xác định trong ví dụ trước. Phương thức show() yêu cầu một phiên bản của FragmentManager và tên thẻ duy nhất cho mảnh.

Tạo bộ chọn ngày

Cách tạo DatePickerDialog cũng giống như cách tạo TimePickerDialog. Điểm khác biệt là hộp thoại bạn tạo cho mảnh.

Để hiển thị DatePickerDialog bằng cách sử dụng DialogFragment, hãy xác định một lớp phân đoạn mở rộng DialogFragment và trả về DatePickerDialog từ phương thức onCreateDialog() của phân đoạn.

Mở rộng DialogFragment cho bộ chọn ngày

Để xác định DialogFragment cho DatePickerDialog, hãy làm như sau:

  • Xác định phương thức onCreateDialog() để trả về một phiên bản của DatePickerDialog.
  • Triển khai giao diện DatePickerDialog.OnDateSetListener để nhận lệnh gọi lại khi người dùng thiết lập ngày.

Ví dụ:

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

Hãy xem lớp DatePickerDialog để biết thông tin về các đối số của hàm khởi tạo.

Bạn chỉ cần một sự kiện, sự kiện này thêm một phiên bản của mảnh này vào hoạt động của bạn.

Hiện bộ chọn ngày

Sau khi xác định một DialogFragment như ví dụ trước, bạn có thể hiển thị bộ chọn ngày bằng cách tạo một phiên bản của DialogFragment và gọi show().

Ví dụ: sau đây là một nút mà khi nhấn vào, hệ thống sẽ gọi một phương thức để hiện hộp thoại:

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

Khi người dùng nhấn vào nút này, hệ thống sẽ gọi phương thức sau:

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

Phương thức này gọi show() trên một phiên bản mới của DialogFragment được xác định trong ví dụ trước. Phương thức show() yêu cầu một phiên bản của FragmentManager và tên thẻ duy nhất cho mảnh.

Sử dụng bộ chọn bằng tính năng tự động điền

Vào năm 2017, Android đã giới thiệu khung Tự động điền, cho phép người dùng lưu dữ liệu có thể dùng để điền vào biểu mẫu trong các ứng dụng. Bộ chọn có thể hữu ích trong các tình huống cần tự động điền, vì công cụ này cung cấp một giao diện người dùng cho phép người dùng thay đổi giá trị của trường lưu trữ dữ liệu ngày hoặc giờ. Ví dụ: trong biểu mẫu thẻ tín dụng, bộ chọn ngày cho phép người dùng nhập hoặc thay đổi ngày hết hạn của thẻ tín dụng.

Vì bộ chọn là hộp thoại nên sẽ không xuất hiện trong một hoạt động cùng với các trường khác. Để cho thấy dữ liệu bộ chọn khi bộ chọn không xuất hiện, bạn có thể sử dụng một thành phần hiển thị khác, chẳng hạn như EditText, có thể cho thấy giá trị khi bộ chọn không xuất hiện.

Theo dự kiến ban đầu, đối tượng EditText sẽ có dữ liệu tự động điền thuộc loại AUTOFILL_TYPE_TEXT. Ngược lại, các dịch vụ tự động điền sẽ lưu dữ liệu dưới dạng AUTOFILL_TYPE_DATE để tạo một cách biểu thị phù hợp. Để giải quyết việc các loại dữ liệu không nhất quán, bạn nên tạo thành phần hiển thị tuỳ chỉnh kế thừa từ EditText và triển khai các phương thức cần thiết để xử lý chính xác các giá trị thuộc loại AUTOFILL_TYPE_DATE.

Hãy thực hiện các bước sau để tạo một lớp con của EditText có thể xử lý các giá trị thuộc loại AUTOFILL_TYPE_DATE:

  1. Tạo lớp kế thừa từ EditText.
  2. Triển khai phương thức getAutofillType(). Phương thức này sẽ trả về AUTOFILL_TYPE_DATE.
  3. Triển khai phương thức getAutofillValue(). Phương thức này sẽ trả về một đối tượng AutofillValue biểu thị ngày theo mili giây. Để tạo đối tượng trả về, hãy sử dụng phương thức forDate() để tạo một đối tượng AutofillValue.
  4. Triển khai phương thức autofill(). Phương thức này cung cấp logic để xử lý tham số AutofillValue thuộc loại AUTOFILL_TYPE_DATE. Để xử lý tham số này, hãy tạo một chuỗi phù hợp biểu thị tham số đó, chẳng hạn như mm/yyyy. Sử dụng cách biểu thị dạng chuỗi để thiết lập thuộc tính text của thành phần hiển thị.
  5. Triển khai chức năng hiển thị bộ chọn khi người dùng muốn chỉnh sửa ngày trong lớp con tuỳ chỉnh của EditText. Khung hiển thị này sẽ cập nhật thuộc tính text bằng một chuỗi biểu thị giá trị mà người dùng chọn trên bộ chọn.

Để biết ví dụ về một lớp con của EditText có nhiệm vụ xử lý các giá trị AUTOFILL_TYPE_DATE, hãy xem mẫu Khung tự động điền trong Java hoặc Kotlin.

Để tìm hiểu thêm về cách hỗ trợ tính năng tự động điền cho thành phần hiển thị tuỳ chỉnh, hãy xem phần Khung tự động điền.