我正在尝试DialogPreference
使用两个NumberPicker
对象来实现 a ,以NumberPicker
在方向更改后恢复最后更改的值:
public class CustomTimePreference extends DialogPreference {
public NumberPicker firstPicker, secondPicker;
private int lastHour = 0;
private int lastMinute = 15;
private int firstMaxValue;
private int tempHour;
private int tempMinute;
private int rotatedHour;
private int rotatedMinute;
private int firstMinValue = 0;
private int secondMinValue=0;
private int secondMaxValue=59;
private String headerText;
private boolean usedForApprox;
public static int getHour(String time){
String[] pieces = time.split(":");
return (Integer.parseInt(pieces[0]));
}
public static int getMinute(String time){
String[] pieces = time.split(":");
return (Integer.parseInt(pieces[1]));
}
public CustomTimePreference(Context context){
this(context, null);
}
public CustomTimePreference(Context context, AttributeSet attrs){
super(context, attrs);
init(attrs);
setDialogLayoutResource(R.layout.custom_time_preference);
setPositiveButtonText(context.getString(R.string.time_preference_set_text));
setNegativeButtonText(context.getString(R.string.time_preference_cancel_text));
}
private void init(AttributeSet attrs){
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomTimePreference);
firstMaxValue = a.getInteger(R.styleable.CustomTimePreference_firstMaxValue,10);
usedForApprox = a.getBoolean(R.styleable.CustomTimePreference_usedForApproximate, false);
headerText = a.getString(R.styleable.CustomTimePreference_customTimeDialogTopText);
a.recycle();
}
public void setFirstPickerValue(int value){
firstPicker.setValue(value);
}
public void setSecondPickerValue(int value){
secondPicker.setValue(value);
}
@Override
protected View onCreateDialogView(){
Log.d("OnCreateDialogView","nanana");
View root = super.onCreateDialogView();
TextView tv = (TextView)root.findViewById(R.id.custom_time_preference_title);
tv.setText(headerText);
firstPicker = (NumberPicker)root.findViewById(R.id.time_preference_first_picker);
firstPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
// TODO Auto-generated method stub
tempHour = newVal;
}
});
secondPicker = (NumberPicker)root.findViewById(R.id.time_preference_second_picker);
secondPicker.setOnValueChangedListener(new NumberPicker.OnValueChangeListener() {
@Override
public void onValueChange(NumberPicker picker, int oldVal, int newVal) {
// TODO Auto-generated method stub
tempMinute = newVal;
}
});
if(usedForApprox){
int smallestValue = MainActivity.getShortestPeriodLength(getContext());
int second = smallestValue % 60;
second-=1;
firstPicker.setMaxValue(second);
secondPicker.setMaxValue(59);
} else {
firstPicker.setMaxValue(firstMaxValue);
secondPicker.setMaxValue(secondMaxValue);
}
firstPicker.setMinValue(firstMinValue);
secondPicker.setMinValue(secondMinValue);
return root;
}
@Override
protected void onBindDialogView(View v){
super.onBindDialogView(v);
firstPicker.setValue(lastHour);
secondPicker.setValue(lastMinute);
}
@Override
protected void onDialogClosed(boolean positiveResult){
super.onDialogClosed(positiveResult);
if(positiveResult){
lastHour = firstPicker.getValue();
lastMinute = secondPicker.getValue();
if (lastHour ==0 && lastMinute == 0){
lastMinute =1;
}
String time = String.valueOf(lastHour) + ":" + String.valueOf(lastMinute);
if(callChangeListener(time)){
persistString(time);
}
}
}
@Override
protected Object onGetDefaultValue(TypedArray a, int index){
return a.getString(index);
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue){
String time = null;
if(restoreValue){
if (defaultValue == null){
time = getPersistedString("00:00");
} else {
time = getPersistedString(defaultValue.toString());
}
} else {
time = defaultValue.toString();
}
lastHour = tempHour = getHour(time);
lastMinute = tempMinute = getMinute(time);
}
private static class SavedState extends BaseSavedState {
// Member that holds the setting's value
// Change this data type to match the type saved by your Preference
String value;
public SavedState(Parcelable superState) {
super(superState);
}
public SavedState(Parcel source) {
super(source);
// Get the current preference's value
value = source.readString(); // Change this to read the appropriate data type
}
@Override
public void writeToParcel(Parcel dest, int flags) {
super.writeToParcel(dest, flags);
// Write the preference's value
dest.writeString(value); // Change this to write the appropriate data type
}
// Standard creator object using an instance of this class
public static final Parcelable.Creator<SavedState> CREATOR =
new Parcelable.Creator<SavedState>() {
public SavedState createFromParcel(Parcel in) {
return new SavedState(in);
}
public SavedState[] newArray(int size) {
return new SavedState[size];
}
};
}
@Override
protected Parcelable onSaveInstanceState() {
final Parcelable superState = super.onSaveInstanceState();
// Check whether this Preference is persistent (continually saved)
/*
if (isPersistent()) {
// No need to save instance state since it's persistent, use superclass state
return superState;
}
*/
// Create instance of custom BaseSavedState
final SavedState myState = new SavedState(superState);
// Set the state's value with the class member that holds current setting value
myState.value = String.valueOf(tempHour) + ":" + String.valueOf(tempMinute);
return myState;
}
@Override
protected void onRestoreInstanceState(Parcelable state) {
// Check whether we saved the state in onSaveInstanceState
if (state == null || !state.getClass().equals(SavedState.class)) {
// Didn't save the state, so call superclass
super.onRestoreInstanceState(state);
return;
}
// Cast state to custom BaseSavedState and pass to superclass
SavedState myState = (SavedState) state;
super.onRestoreInstanceState(myState.getSuperState());
// Set this Preference's widget to reflect the restored state
rotatedHour = getHour(myState.value);
rotatedMinute = getMinute(myState.value);
firstPicker.setValue(rotatedHour);
secondPicker.setValue(rotatedMinute);
}
}
有两个问题:
- 当我打开我的自定义首选项,更改其中一个选择器的值,然后将手机从纵向旋转到横向时,应用程序崩溃。错误是
NuLLpointerException
,它指向我尝试将恢复的值分配给我的一个NumberPicker
对象的行。 - 这更像是一个问题而不是一个问题。我从 Android 开发者主页复制了 BaseSavedState 内部类和 onSaveInstanceState()、onRestoreInstanceState() 函数,但是当我尝试应用程序在方向更改时恢复值时,手机显示的是持久值,而不是方向更改前的最新值。当我尝试使用日志消息检查代码时,我发现我的手机在 SaveInstanceState isPersisted 检查退出了该功能并且根本不使用 BaseSavedState 对象。我注释掉了 isPersisted 检查,所以现在我可以从 BaseSavedState 对象中保存和检索值,但在那之后问题就出现了。1 出现。所以我的问题是,如果偏好是持久的,那么跳过 BaseSavedState 对象创建的原因是什么。