In the spaced repetition app I’m building, I wanted to allow people to pick a time for the study reminder notifications to show up on. There is a built-in AndroidX Preference Library that is meant to help with this, however I found that there’s no built-in way to display a TimePicker dialog as part of the preference option. Some tinkering are still required, and here’s the solution that works for me.
Before heading to the code, here’s a quick recap of what will be needed. Think of them as the building blocks that have to connect together.
- A class that derives from
DialogPreference. This part is for managing the Preference aspect of the dialog preference to be displayed, such as its message, buttons, as well as for saving and retrieving the value selected. The library has some built-in dialog preferences (EditTextPreference, ListPreference, MultiSelectListPreference), but no such thing as TimePickerPreference, so we’ll have to make ourselves here.
- A class that derives from
PreferenceDialogFragmentCompat. This part is for managing the visual aspect of the dialog preference to be displayed. This is where we will actually create and display the
TimePicker, for instance.
- XML layout for the main preference page. This is used to for the visual aspect of the preferences page that’s shown to the user.
- Lastly, a fragment that derives from
PreferenceFragmentCompat, which essentially is a special type of fragment that’s meant to be used for displaying the preferences page based on the XML layout, and for wrangling various display options related to it.
First thing we want to make is the TimePickerPreference. Here’s how my code looks like:
Above, I override
onSetInitialValue() so that I can fill the preference’s summary with the actual time. The idea is to allow people to see the currently selected time, which should look like this:
With custom dialog preference like this, I found that the summary area is what’s commonly used to show the current value of that preference.
The two functions
getPersistedMinutesFromMidnight() are to be used for saving and retrieving the value related to this preference.
After the preference aspect is created, now we set up the actual dialog. Here’s the code that I have:
onCreateDialogView(), we generate the TimePicker to be displayed.
onBindDialogView(), we grab the current hour/minute preference value, and set that value into the TimePicker. The goal is to make it so that when someone first opens the TimePicker dialog, the clock already shows the current value instead of starting from zero.
(preference as TimepickerPreference) is needed here because without it, the compiler does not now that the current preference is a custom TimePickerPreference, and hence will not be able to find the function we need.
onDialogClosed(), we save the value selected by the user after clicking the positive button.
3. XML Layout
Here’s my preference XML file:
The interesting part might be
<black.old.spacedrepetitionowl.TimepickerPreference> which indeed is the class we created on step 1. During run-time, the
android:summary part is programmatically modified and filled in both within
TimePickerPreference (on initial opening of the preference screen), and
TimePickerDialogPreference (after user picked a time).
This is the regular fragment that we’ll use to display the preference screen. Here’s my file:
First, we’re pulling the XML layout inside
Next, since we want to display our own custom dialog preference, we need to override
onDisplayPreferenceDialog(). Here, we specifically want to check if the currently selected preference is our custom preference,
TimePickerPreference. If it is, we instantiate a new
TimePickerPreferenceDialog and display it. If it’s a different type of dialog preference (let’s say it’s one of the three built-in dialog preferences mentioned earlier), we let it be handled automatically by the superclass.
And that’s it! This is just a small example but hopefully is a good starting point if you want to create a different kind of custom dialog preference 🙂