Custom Date/Time PickerDialog Android

1.Giới thiệu:

Trong bài này, mình sẽ giới thiệu cho các bạn về Time Selection trong Android. Có nhiều loại Time Selection: AnalogClock, Chronometor, DatePickerDialog, TimePickerDialog. Nhưng mình chỉ giới thiệu 2 control cuối phổ biến, các control khác các bạn tự tìm hiểu thêm trên mạng:

2.Code

Mình sẽ sử dụng mô hình MVVM trong Android. Đầu tiên tạo 1 interface riêng chứa Date/Time PickerDialog, tên là TimeManagement.java

public interface TimeManagement {
    TimeManagement dialogDatePicker(DatePickerDialog.OnDateSetListener onDateSetListener);

    void showDatePickerDialog();

    TimeManagement dialogTimePicker(TimePickerDialog.OnTimeSetListener onTimeSetListener);

    void showTimePickerDialog();
}

Tiếp theo tạo class implement interface TimeManagement để build và custom Date/Time PickerDialog, đặt tên là TimeManagementImpl.java

public class TimeManagementImpl implements TimeManagement {
    private static final String DATE_PICKER = "mDatePicker";
    private static final String DAY_FIELD = "day";
    private static final String ID = "id";
    private static final String ANDROID = "android";
    private Context mContext;
    private DatePickerDialog mDatePickerDialog;
    private TimePickerDialog mTimePickerDialog;
    private Calendar mCalendar;

    public DialogManagerImpl(Context context) {
        mContext = context;
        mCalendar = Calendar.getInstance();
        }
        
    @Override
    public TimeManagement dialogDatePicker(DatePickerDialog.OnDateSetListener onDateSetListener) {
        mDatePickerDialog =
                new DatePickerDialog(mContext, onDateSetListener, mCalendar.get(Calendar.YEAR),
                        mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH));
        return this;
    }

    @Override
    public void showDatePickerDialog() {
        if (mDatePickerDialog == null) {
            return;
        }
        mDatePickerDialog.show();
    }

    @Override
    public TimeManagement dialogTimePicker(TimePickerDialog.OnTimeSetListener onTimeSetListener) {
        mTimePickerDialog = new TimePickerDialog(mContext, onTimeSetListener,
                mCalendar.get(Calendar.HOUR_OF_DAY), mCalendar.get(Calendar.MINUTE), true);
        return this;
    }

    @Override
    public void showTimePickerDialog() {
        if (mTimePickerDialog == null) {
            return;
        }
        mTimePickerDialog.show();
    }
    }

Tại class ViewModel, implements DatePickerDialog.OnDateSetListener (Với Datepicker) (hay TimePickerDialog.OnTimeSetListener(Với TimePicker)).

//DatePicker Dialog, tương tự đối với TimePicker Dialog
@Override
    public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {
        setDate(String.valueOf(new StringBuilder().append(date).append("/").append(month).append("/").append(year).append("")));
    }
    
 // Even onClick
     public void onPickDate(View view) {
        mTimeManagement.showDatePickerDialog();
    }

Bạn có 5 theme có thể lựa chọn cho Date/Time Picker Dialog: mDatePickerDialog = new DatePickerDialog(mContext, X, onDateSetListener, mCalendar.get(Calendar.YEAR), mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH)); Thay vào X lần lượt các giá trị, ta sẽ được như hình minh họa

  1. THEME_DEVICE_DEFAULT_LIGHT
  2. AlertDialog.THEME_DEVICE_DEFAULT_DARK
  3. AlertDialog.THEME_HOLO_DARK
  4. AlertDialog.THEME_HOLO_LIGHT
  5. AlertDialog.THEME_TRADITIONAL

3. Custom

Đối với các theme HOLO hay TRADITIONAL, ta có thể custom để chỉ hiển thị tháng và năm, hoặc chỉ năm, như sau : Tại method buid dialog như đã nói ở trên, ta tiến hành bổ sung như sau

 @Override
    public TimeManagement dialogDatePicker(DatePickerDialog.OnDateSetListener onDateSetListener) {
        mDatePickerDialog =
                new DatePickerDialog(mContext, onDateSetListener, mCalendar.get(Calendar.YEAR),
                        mCalendar.get(Calendar.MONTH), mCalendar.get(Calendar.DAY_OF_MONTH));
                        
                        try {
            Field[] datePickerDialogFields = mDatePickerDialog.getClass().getDeclaredFields();
            for (Field datePickerDialogField : datePickerDialogFields) {
                if (datePickerDialogField.getName().equals("mDatePicker")) {
                    datePickerDialogField.setAccessible(true);
                    DatePicker datePicker =
                            (DatePicker) datePickerDialogField.get(mDatePickerDialog);
                    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        int daySpinnerId =
                                Resources.getSystem().getIdentifier("day", "id", "android");
                        if (daySpinnerId != 0) {
                            View daySpinner = datePicker.findViewById(daySpinnerId);
                            if (daySpinner != null) {
                            //Ẩn cột date, chỉ còn lại month và year
                                daySpinner.setVisibility(View.GONE);
                            }
                        }
                    }
                }
            }
        } catch (IllegalAccessException e) {
            Log.e(TAG, "IllegalAccessException: ", e);
        }
        return this;
    }

Code trên mình đã ẩn đi cột date, bạn có thể ẩn với month hay year nếu muốn, TimePicker cũng tương tự như vậy. Chúc thành công