Extending DialogFragment for a MaterialDatePicker

447 Views Asked by At

I want to migrate from DatePickerDialog to MaterialDatePicker. I ran into a problem when calling getDialog from MaterialDatePicker with the dialog result always null.

Is this a bug, or is the feature not supported for MaterialDatePicker?

DatePickerDialog

private static class BirthDateUpdater extends DialogFragment implements DatePickerDialog.OnDateSetListener {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        // create calendar instance
        final Calendar c = Calendar.getInstance();

        // set calendar to birthdate
        c.setTimeInMillis(getBirthDate().getTime());

        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(getActivity(), this, year, month, day);
    }

    public void onDateSet(DatePicker view, int year, int month, int day) {
        // process date selected in here
    }
}

MaterialDatePicker problem in here - result of picker.getDialog() always null?

public static class BirthDateUpdater extends DialogFragment implements 
    MaterialPickerOnPositiveButtonClickListener<Long>, 
    DialogInterface.OnCancelListener {
    
    private Dialog dialog;

    public BirthDateUpdater() {
    }

    @NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        try {
            // builder
            MaterialDatePicker.Builder<Long> builder = MaterialDatePicker.Builder.datePicker();
            builder.setTitleText("Select Date");

            // set date to BirthDate
            builder.setSelection(getBirthDate().getTime());

            // picker
            MaterialDatePicker<Long> picker = builder.build();
            
            // add event
            picker.addOnPositiveButtonClickListener(this);
            picker.addOnCancelListener(this);

            // dialog
            dialog = picker.getDialog(); // error in here (dialog is null)?

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return dialog;
    }

    @Override
    public void onPositiveButtonClick(Long selection) {
        try {
            Calendar dateSelected = Calendar.getInstance();
            dateSelected.setTimeInMillis(selection);
            
            // process date selected in here
            
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    @Override
    public void onCancel(@NonNull DialogInterface dialog) {
        dialog.dismiss();
    }
}
1

There are 1 best solutions below

0
On BEST ANSWER

MaterialDatePicker is already DialogFragment. In your case picker.getDialog() returns null because under the hood the DialogFragment write value to DialogFragment.mDialog(value of this filed returns picker.getDialog()) filed from life-cycle callback onCreateDialog() which will be called async after invoke the the dialog's show method, i.e. when you call to picker.show(fragmentManager) then in picker's onCreateDialog you will can get not null value from getDialog() method.

In your case you should not extend DialogFragment or MaterialDatePicker (it is final ) instead that you can just create method like birthDateUpdater:

public DialogFragment birthDateUpdater() {
            MaterialDatePicker.Builder<Long> builder = MaterialDatePicker.Builder.datePicker();
            builder.setTitleText("Select Date");

            // set date to BirthDate
            builder.setSelection(getBirthDate().getTime());

            // picker
            MaterialDatePicker<Long> picker = builder.build();
            
            // add event
            picker.addOnPositiveButtonClickListener(selection -> {
              try {
              Calendar dateSelected = Calendar.getInstance();
              dateSelected.setTimeInMillis(selection);
            
               // process date selected in here
            
               } catch (Exception ex) {
                 ex.printStackTrace();
               }
            });
            picker.addOnCancelListener(dialog -> {
               dialog.dismiss();
            });
            return picker
}

Or create class, factory, whatever which will be encapsulate this logic.