When developing applications for Google Android, there's a great way to implement your preferences using an xml, much like you would for a regular layout. The added benifit of doing it this way is that you don't have to implement how the preference values are saved. However, one of the problems is that there are only a couple of preference types implemented. For my latest application, I needed to let the user save a specific time. Where there is a TimePicker widget, there is not TimePickerPreference that extends the Preference class. So I wrote my own. // Please note this must be the package if you want to use XML-based preferences package android.preference; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.widget.TimePicker; /** * A preference type that allows a user to choose a time */ public class TimePickerPreference extends DialogPreference implements TimePicker.OnTimeChangedListener { /** * The validation expression for this preference */ private static final String VALIDATION_EXPRESSION = "[0-2]*[0-9]:[0-5]*[0-9]"; /** * The default value for this preference */ private String defaultValue; /** * @param context * @param attrs */ public TimePickerPreference(Context context, AttributeSet attrs) { super(context, attrs); initialize(); } /** * @param context * @param attrs * @param defStyle */ public TimePickerPreference(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); initialize(); } /** * Initialize this preference */ private void initialize() { setPersistent(true); } /* * (non-Javadoc) * * @see android.preference.DialogPreference#onCreateDialogView() */ @Override protected View onCreateDialogView() { TimePicker tp = new TimePicker(getContext()); tp.setOnTimeChangedListener(this); int h = getHour(); int m = getMinute(); if (h >= 0 && m >= 0) { tp.setCurrentHour(h); tp.setCurrentMinute(m); } return tp; } /* * (non-Javadoc) * * @see * android.widget.TimePicker.OnTimeChangedListener#onTimeChanged(android * .widget.TimePicker, int, int) */ @Override public void onTimeChanged(TimePicker view, int hour, int minute) { persistString(hour + ":" + minute); } /* * (non-Javadoc) * * @see android.preference.Preference#setDefaultValue(java.lang.Object) */ @Override public void setDefaultValue(Object defaultValue) { // BUG this method is never called if you use the 'android:defaultValue' attribute in your XML preference file, not sure why it isn't super.setDefaultValue(defaultValue); if (!(defaultValue instanceof String)) { return; } if (!((String) defaultValue).matches(VALIDATION_EXPRESSION)) { return; } this.defaultValue = (String) defaultValue; } /** * Get the hour value (in 24 hour time) * * @return The hour value, will be 0 to 23 (inclusive) */ private int getHour() { String time = getPersistedString(this.defaultValue); if (time == null || !time.matches(VALIDATION_EXPRESSION)) { return -1; } return Integer.valueOf(time.split(":")[0]); } /** * Get the minute value * * @return the minute value, will be 0 to 59 (inclusive) */ private int getMinute() { String time = getPersistedString(this.defaultValue); if (time == null || !time.matches(VALIDATION_EXPRESSION)) { return -1; } return Integer.valueOf(time.split(":")[1]); } } |
|||

Error
It doesn't save the user preference, if the user types the numbers in the box themselves ( instead of using the + / - )
Feel free to suggest updates
If you find out what event handler is called when a user manually enters a value, let me know so I can update the code here.
Thanks,
Eric
Thanks mate excellent
Thanks mate excellent implementation of a time picker
package doesn't need to be android.preference
hi, great work!
saved me a lot of time.
I just wanna say that you can change the package these preferences lie in,
if you specify entire package in XML-file:
Kris
Problem again again
Ok, I found that if I call tp.setIs24HourView(true); before tp.setOnTimeChangedListener(this); it works fine. Thanks for this great class!
Problem again
Never mind my previous post! The problem was that I added tp.setIs24HourView(true); to the onCreateDialogView method, since I'm from Europe and we use a 24 hour clock. ;)
However, that seems to mess it up. :( How can I set it to use a 24 hour clock by default?
Problem
I've been eager to use this, but I haven't been able to get it working.
When I set a preference using this class, it gets set properly in the shared prefs xml file. However, whenever I open the preference again, the time picker is set to the current time. It seems that the onTimeChanged method is called immediately after the time picker is created, with its parameters set to the current time.
Did anyone else experience this? I don't know how to solve it ... :(
Cancel behavior
I might be missing something but this seems to always persist the value even if you cancel the TimePicker. I changed onTimeChanged to store to a local variable and then did a @Override on onDialogClosed to get the state of the dialog.
If the user said 'ok' then persist the string (In my implementation I didn't make it persist by default, hence the 'isPersistent()'). If the user canceled then I change nothing
private int mHour = 0, mMinute = 0; @Override public void onTimeChanged(TimePicker view, int hour, int minute) { mHour = hour; mMinute = minute; } @Override public void onDialogClosed(boolean positiveResult) { if( positiveResult ) { if( isPersistent() ) persistString(mHour + ":" + mMinute); mValueText.setText( getNiceTimestring() ); } }Update for latest Android release
From an email:
I had to modify your TimePickerPreference code a little as it did not respond to an OnPreferenceChangeListener. The change made is just this:
DatePicker
I've been trying to implement a similar pref for DatePicker ... however I'm having a few problems. Had any luck with that?
RE: DatePicker
I haven't need to use a Date preference value, so I haven't created this kind of class for DatePicker. If you're having problems, then I suggest posting to the Android Developers group.
Thanks
Thanks for saving me the work. Using this in my Android project now :)
Can we use your code ?
What's the license of this code ?
No license
There is no license, you can use however you want to.
layout
is there another layout or the normal if u create a new file????
This is a class, so it should
This is a class, so it should be a new file. I'm not exactly sure what you're asking.