在自定义日选取器中使用DialogPreference

时间:2014-04-09 02:19:16

标签: android android-intent sharedpreferences android-preferences preferenceactivity

我正在尝试显示自定义日期选择器。这是我到目前为止所做的。

menu_settings.xml:     

<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" > 
    <PreferenceCategory android:title="@string/pref_user_profile" >
        <com.example.DatePickerDialogPreference
                android:dialogLayout="@layout/date_time_dialog"
                android:key="prefDayPicker"                 
                android:title="Pick a Day"
                android:summary="Day Picker" 
                android:positiveButtonText="Set"
                android:negativeButtonText="Cancel" />      
    </PreferenceCategory>
</PreferenceScreen>

date_time_dialog.xml:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/DateTimeDialog"
    android:layout_width="277dp"
    android:layout_height="217dp"
    android:background="#999999" >

    <com.example.customdatepicker.DateTimePicker
    android:id="@+id/DateTimePicker"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_centerHorizontal="true" />
</RelativeLayout>

datetimepicker.xml:

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/DateTimePicker"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:fitsSystemWindows="true"
    android:padding="5dip" >

    <LinearLayout
    android:layout_width="277dp"
    android:layout_height="153dp"
    android:layout_centerHorizontal="true"
    android:layout_centerInParent="true"
    android:background="#000000"
    android:baselineAligned="true"
    android:orientation="horizontal" >

    <LinearLayout
        android:id="@+id/date_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="5dp"
        android:layout_marginTop="5dp"
        android:layout_weight="1"
        android:gravity="center"
        android:orientation="vertical" >

        <Button
        android:id="@+id/date_plus"
        android:layout_width="74dp"
        android:layout_height="41dp"
        android:background="@drawable/image_button_up" />

        <EditText
        android:id="@+id/date_display"
        android:layout_width="74dp"
        android:layout_height="49dp"
        android:background="@drawable/picker_middle"
        android:gravity="center"
        android:inputType="number"
        android:padding="1dp"
        android:singleLine="true"
        android:textColor="#000000"
        android:textSize="28sp" />

        <Button
        android:id="@+id/date_minus"
        android:layout_width="74dp"
        android:layout_height="41dp"
        android:background="@drawable/image_button_down" />
    </LinearLayout>

    </LinearLayout>

</RelativeLayout>

DayTimePicker.java:

public class DateTimePicker extends RelativeLayout {
        private View myPickerView;

        private Button date_plus;
        private EditText date_display;
        private Button date_minus;

        private Calendar cal;

        public DateTimePicker(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }

        public DateTimePicker(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);

            LayoutInflater inflator = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            myPickerView = inflator.inflate(R.layout.datetimepicker, null);
            this.addView(myPickerView);

            initializeReference();

        } 
        private void init(Context mContext) {
            LayoutInflater inflator = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            myPickerView = inflator.inflate(R.layout.datetimepicker, null);
            this.addView(myPickerView);

            initializeReference();
        }
        private void initializeReference() {
            date_plus = (Button) myPickerView.findViewById(R.id.date_plus);
            date_plus.setOnClickListener(date_plus_listener);
            date_display = (EditText) myPickerView.findViewById(R.id.date_display);
            date_display.addTextChangedListener(date_watcher);
            date_minus = (Button) myPickerView.findViewById(R.id.date_minus);
            date_minus.setOnClickListener(date_minus_listener);

            initData();
            initFilterNumericDigit();
        }
        public void initData() {
            cal = Calendar.getInstance();   
            date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));
        }

        private void initFilterNumericDigit() {
            try {
                date_display.setFilters(new InputFilter[] { new InputFilterMinMax(1, cal.getActualMaximum(Calendar.DAY_OF_MONTH)) });

            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        private void changeFilter() {
            try {
                date_display.setFilters(new InputFilter[] { new InputFilterMinMax(1, cal.getActualMaximum(Calendar.DAY_OF_MONTH)) });
            } catch (Exception e) {
                date_display.setText("" + cal.get(Calendar.DAY_OF_MONTH));
                e.printStackTrace();
            }
        }
        public void setTimeChangedListener(TimeWatcher listener) {
            this.mTimeWatcher = listener;
        }

        public void removeTimeChangedListener() {
            this.mTimeWatcher = null;
        }

        View.OnClickListener date_plus_listener = new View.OnClickListener() {          
            public void onClick(View v) {

                try {
                    date_display.requestFocus();
                    cal.add(Calendar.DAY_OF_MONTH, 1);

                    date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));

                    sendToListener();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        View.OnClickListener date_minus_listener = new View.OnClickListener() {

            public void onClick(View v) {

                try {
                    date_display.requestFocus();
                    cal.add(Calendar.DAY_OF_MONTH, -1);

                    date_display.setText(String.valueOf(cal.get(Calendar.DAY_OF_MONTH)));

                    sendToListener();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        class InputFilterMinMax implements InputFilter {

            private int min, max;

            public InputFilterMinMax(int min, int max) {
                this.min = min;
                this.max = max;
            }

            public CharSequence filter(CharSequence source, int start, int end,
                    Spanned dest, int dstart, int dend) {
                try {
                    int input = Integer.parseInt(dest.toString()
                            + source.toString());
                    if (isInRange(min, max, input)) {
                        return null;
                    }
                } catch (NumberFormatException nfe) {
                }
                return "";
            }

            private boolean isInRange(int a, int b, int c) {
                return b > a ? c >= a && c <= b : c >= b && c <= a;
            }
        }

        public void reset() {
            cal = Calendar.getInstance();
            initFilterNumericDigit();
            initData();             
        }

        synchronized private void sendToListener() {

            if (mDateWatcher != null) {
                mDateWatcher.onDateChanged(cal);
            }
        }

        public int getDay() {
            return Integer.parseInt(date_display.getText().toString());
        }

        public void setDateChangedListener(DateWatcher listener) {
            this.mDateWatcher = listener;
        }

        public void removeDateChangedListener() {
            this.mDateWatcher = null;
        }       

        TextWatcher date_watcher = new TextWatcher() {          
            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {
            }

            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
            }

            public void afterTextChanged(Editable s) {
                try {
                    if (s.toString().length() > 0) {
                        cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(s.toString()));

                        sendToListener();
                    }
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        DateWatcher mDateWatcher = null;        
}

DatePickerDialogPreference.java:

public class DatePickerDialogPreference extends DialogPreference {

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

    @Override
    protected void onBindDialogView(View view) {        
    super.onBindDialogView(view);
    }

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


    // HERE, HOW DO I GET VALUES OF SELECTED DAY FROM CUSTOM DAY PICKER????
    // Tried Dialog dialog = getDialog(); But it returns null, so can't do much.

    persistBoolean(positiveResult);
    }
}

上面的代码显示了自定义首选项“选择一天”,单击其中显示自定义日期选择器。

除了我不知道如何获取在日期选择器中选择的值之外,所有内容都正确显示。如何在首选项中存储选定的日期选择器值。

任何人都可以告诉我该怎么做吗?

谢谢!

1 个答案:

答案 0 :(得分:0)

您可以通过绑定PreferenceActivity中的值更改事件来执行此操作,例如 -

/**
 * A preference value change listener that updates the preference's summary
 * to reflect its new value.
 */
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() {
    @Override
    public boolean onPreferenceChange(Preference preference, Object value) {
        String stringValue = value.toString();

        if (preference instanceof RingtonePreference) {
            // For ringtone preferences, look up the correct display value
            // using RingtoneManager.
            if (TextUtils.isEmpty(stringValue)) {
                // Empty values correspond to 'silent' (no ringtone).
                preference.setSummary(R.string.pref_ringtone_silent);

            } else {
                Ringtone ringtone = RingtoneManager.getRingtone(
                        preference.getContext(), Uri.parse(stringValue));

                if (ringtone == null) {
                    // Clear the summary if there was a lookup error.
                    preference.setSummary(null);
                } else {
                    // Set the summary to reflect the new ringtone display
                    // name.
                    String name = ringtone
                            .getTitle(preference.getContext());
                    preference.setSummary(name);
                }
            }

        } else {
            // For all other preferences, set the summary to the value's
            // simple string representation.
            preference.setSummary(stringValue);
        }
        return true;
    }
};

/**
 * Binds a preference's summary to its value. More specifically, when the
 * preference's value is changed, its summary (line of text below the
 * preference title) is updated to reflect the value. The summary is also
 * immediately updated upon calling this method. The exact display format is
 * dependent on the type of preference.
 *
 * @see #sBindPreferenceSummaryToValueListener
 */
private static void bindPreferenceSummaryToValue(Preference preference) {
    // Set the listener to watch for value changes.
    preference.setOnPreferenceChangeListener(sBindPreferenceSummaryToValueListener);

    // Trigger the listener immediately with the preference's
    // current value.
    String defaultSharedPrefs = PreferenceManager.getDefaultSharedPreferences(preference.getContext()).getString(preference.getKey(), "");
    sBindPreferenceSummaryToValueListener.onPreferenceChange(preference, defaultSharedPrefs);
}

然后,在构建首选项列表时,注册需要此绑定的控件 -

bindPreferenceSummaryToValue(findPreference("pack_first_pill"));