Providing default values to a custom View via the XML
I used this post recently to get started on a custom Time picker for my app. It works pretty well, but I needed to add default values to it from the XML. I found another post which did just that. I am just going to show the combined result here.
First here is the code for the Time picker. This is mostly the same as that provided by Eric Bessette with the addition of the default reading stuff. The relevant parts are in bold.
package ie.nolantech.flow;
import ie.nolantech.util.TimeSplitter;
import android.content.Context;
import android.preference.DialogPreference;
import android.text.format.DateFormat;
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 {
private static final String TAG = "TimePickerPreference";
private int mHour = 0, mMinute = 0;
private String defaultTime;
/**
* The validation expression for this preference
*/
private static final String VALIDATION_EXPRESSION = "[0-2]*[0-9][0-5]*[0-9]";
/**
* @param context
* @param attrs
*/
public TimePickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
defaultTime = attrs.getAttributeValue(
"http://schemas.android.com/apk/res/ie.nolantech.flow",
"defaultTime");
Log.d(TAG, "" + defaultTime);
}
/**
* @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.setIs24HourView(DateFormat.is24HourFormat(getContext()));
tp.setOnTimeChangedListener(this);
int h = getHour();
int m = getMinute();
if (h >= 0 && m >= 0) {
tp.setCurrentHour(h);
tp.setCurrentMinute(m);
}
return tp;
}
@Override
public void onTimeChanged(TimePicker view, int hour, int minute) {
Log.d(TAG, "on time changed:" + hour + ":" + minute, getContext());
mHour = hour;
mMinute = minute;
}
@Override
public void onDialogClosed(boolean positiveResult) {
Log.d(TAG, "onDialogClosed:" + positiveResult + mHour + ":" + mMinute,
getContext());
String result = Utils.pad("" + mHour, '0', 2)
+ Utils.pad("" + mMinute, '0', 2);
if (positiveResult) {
if (isPersistent()) {
persistString(result);
}
callChangeListener(result);
}
}
/**
* 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.defaultTime);
if (time == null || !time.matches(VALIDATION_EXPRESSION)) {
return -1;
}
TimeSplitter ts = new TimeSplitter(Utils.pad(time, '0', 4));
return ts.hours;
}
/**
* Get the minute value
*
* @return the minute value, will be 0 to 59 (inclusive)
*/
private int getMinute() {
String time = getPersistedString(this.defaultTime);
if (time == null || !time.matches(VALIDATION_EXPRESSION)) {
return -1;
}
TimeSplitter ts = new TimeSplitter(Utils.pad(time, '0', 4));
return ts.minutes;
}
}
Then you need a file called attrs.xml. Drop it into your values directory:
This just defines the attribute that you are going to use from your TimePickerPreference.
Finally in your preferences xml file add your custom namespace:
First here is the code for the Time picker. This is mostly the same as that provided by Eric Bessette with the addition of the default reading stuff. The relevant parts are in bold.
package ie.nolantech.flow;
import ie.nolantech.util.TimeSplitter;
import android.content.Context;
import android.preference.DialogPreference;
import android.text.format.DateFormat;
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 {
private static final String TAG = "TimePickerPreference";
private int mHour = 0, mMinute = 0;
private String defaultTime;
/**
* The validation expression for this preference
*/
private static final String VALIDATION_EXPRESSION = "[0-2]*[0-9][0-5]*[0-9]";
/**
* @param context
* @param attrs
*/
public TimePickerPreference(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
defaultTime = attrs.getAttributeValue(
"http://schemas.android.com/apk/res/ie.nolantech.flow",
"defaultTime");
Log.d(TAG, "" + defaultTime);
}
/**
* @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.setIs24HourView(DateFormat.is24HourFormat(getContext()));
tp.setOnTimeChangedListener(this);
int h = getHour();
int m = getMinute();
if (h >= 0 && m >= 0) {
tp.setCurrentHour(h);
tp.setCurrentMinute(m);
}
return tp;
}
@Override
public void onTimeChanged(TimePicker view, int hour, int minute) {
Log.d(TAG, "on time changed:" + hour + ":" + minute, getContext());
mHour = hour;
mMinute = minute;
}
@Override
public void onDialogClosed(boolean positiveResult) {
Log.d(TAG, "onDialogClosed:" + positiveResult + mHour + ":" + mMinute,
getContext());
String result = Utils.pad("" + mHour, '0', 2)
+ Utils.pad("" + mMinute, '0', 2);
if (positiveResult) {
if (isPersistent()) {
persistString(result);
}
callChangeListener(result);
}
}
/**
* 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.defaultTime);
if (time == null || !time.matches(VALIDATION_EXPRESSION)) {
return -1;
}
TimeSplitter ts = new TimeSplitter(Utils.pad(time, '0', 4));
return ts.hours;
}
/**
* Get the minute value
*
* @return the minute value, will be 0 to 59 (inclusive)
*/
private int getMinute() {
String time = getPersistedString(this.defaultTime);
if (time == null || !time.matches(VALIDATION_EXPRESSION)) {
return -1;
}
TimeSplitter ts = new TimeSplitter(Utils.pad(time, '0', 4));
return ts.minutes;
}
}
Then you need a file called attrs.xml. Drop it into your values directory:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="TimePickerPreference">
<attr format="integer" name="defaultTime" />
</declare-styleable>
</resources>
xmlns:nt="http://schemas.android.com/apk/res/ie.nolantech.flow"
And the new defaultValue attribute to your custom View layout:
<ie.nolantech.flow.TimePickerPreference
nt:defaultTime="2247"
android:key="bed_time"
android:summary="don't disturb me after this time(e.g. 2200 for 8pm)"
android:title="Bed time" >
</ie.nolantech.flow.TimePickerPreference>
That's it. Works well. At the moment the time picker still does not handle typing correctly. If a user enters the value from the keyboard it will not register with the View. I will get this fixed at some point.
Comments
Post a Comment