Custom DatePicker as Preference does not keep valu

2019-03-13 21:40发布

I created a DatePickerPreference, i.e. I extended DialogPreference and created a DatePicker object inside and had it working almost perfectly. It changes values when you click the arrows up and down and saves the value you select.

However, if you click inside the field and types the new value there, it doesn't save the updated value! When using the arrows, the onDateChanged() method is always called; when user enters the field and edits it, it will only call onDateChanged if he selects another field (and in this case, if he edits the last field and just hit OK, the last edit will be ignored). I found that Eric Besette posted a similar problem with his TimePickerPreference

Here is my code:


    public class DatePickerPreference extends DialogPreference implements  
OnDateChangedListener, OnDateSetListener {

    @Override
    protected View onCreateDialogView() {
        DatePicker picker = new DatePicker(getContext());
        mDate = getPersistedLong(System.currentTimeMillis());

        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(mDate);

        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int month = calendar.get(Calendar.MONTH);
        int year = calendar.get(Calendar.YEAR);

        picker.init(year, month, day, this);
        return picker;
    }

    public void onDateChanged(DatePicker view, int year, int monthOfYear,  
            int dayOfMonth) {
        mDate = (new Date(year - 1900, monthOfYear, dayOfMonth)).getTime();
    }

    public void onDateSet(DatePicker view, int year, int monthOfYear,  
            int dayOfMonth) {
        onDateChanged(view, year, monthOfYear, dayOfMonth);
    }

    @Override
    public void setDefaultValue(Object defaultValue) {
        super.setDefaultValue(String.valueOf((  
            new Date(String.valueOf(defaultValue))).getTime()));
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);

        if(positiveResult) {
            if(isPersistent()) {
                persistLong(mDate);
            }
            callChangeListener(String.valueOf(mDate));
        }
    }

    public int getYear() { /*(...)*/ }
    public int getMonth() { /*(...)*/ }
    public int getDay() { /*(...)*/ }

    public DatePickerPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public DatePickerPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    public void init() { setPersistent(true); }
    public void setDate(Date date) { mDate = date.getTime(); }
    public void setDate(long milisseconds) { mDate = milisseconds; }

    public String getDate(int style) {
        return DateFormat.getDateInstance(style).format(new Date(mDate));
    }

    public long getDate() { return mDate; }

    private long mDate;
    public static final int DATE_SHORT = DateFormat.SHORT;
    public static final int DATE_MEDIUM = DateFormat.MEDIUM;
    public static final int DATE_LONG = DateFormat.LONG;
    public static final int DATE_FULL = DateFormat.FULL;
    public static final int DATE_DEFAULT = DateFormat.DEFAULT;
}

3条回答
劳资没心,怎么记你
2楼-- · 2019-03-13 21:52

Since this class extends the DialogPreference class, it already handles changing the SharedPreference using the buttons. To correctly update your date variable after the user types the new date, you need to update the SharedPreference manually.

You can do this as follows:

SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
SharedPreferences.Editor preferences = prefs.edit();
preferences.putLong("mdate_key", mDate.getTime());
preferences.commit();

Here, mdate_key will correspond to the DatePickerPreference key used in the PreferenceActivity XML file.

I recommend either doing this in onDateChanged() or onDestroy().

查看更多
Emotional °昔
3楼-- · 2019-03-13 22:02
乱世女痞
4楼-- · 2019-03-13 22:03

I had the same issue. The solution is very simple. The date picker updates the edited values only when it losts focus, so before getting the values you have to call:

datePicker.clearFocus();

After this call you can call:

selectedDay = datePicker.getDayOfMonth();
selectedMonth = datePicker.getMonth();

and have the values updated.

查看更多
登录 后发表回答