尝试创建获取时间段的自定义对话框首选项时出现问题

时间:2014-04-23 20:19:16

标签: android android-fragments

我正在尝试在我的UI中使用首选项来从用户获取值并填充到对象中。因此,我不想坚持他们。我创建了一个自定义的TimePeriodPreference来获取时间间隔。

1)为什么我的自定义对话框偏好中的数字选择器缺少熟悉的+控件?此外,他们不允许输入文本。

2)何时(在哪种方法中)我应该访问号码选择器来收获价值好吗? onDialogClosed()为时已晚。它给了我一个空指针错误,因为那时小部件显然丢失了。

    04-23 13:09:04.732: E/AndroidRuntime(9794): java.lang.NullPointerException
04-23 13:09:04.732: E/AndroidRuntime(9794):     at com.mypreferences.TimePeriodPreference.onDialogClosed(TimePeriodPreference.java:52)
04-23 13:09:04.732: E/AndroidRuntime(9794):     at android.preference.DialogPreference.onDismiss(DialogPreference.java:382)
04-23 13:09:04.732: E/AndroidRuntime(9794):     at android.app.Dialog$ListenersHandler.handleMessage(Dialog.java:1235)

仅供参考,完整的代码在这里 https://www.dropbox.com/s/pul1eximvsfxsvz/DataManagementPreferenceActivity.zip

我按照这里的步骤操作: http://developer.android.com/guide/topics/ui/settings.html#Custom

也在这里: Concise way of writing new DialogPreference classes?

尝试按照示例here移动它,也会导致空指针

@Override
protected View onCreateDialogView() {
    hourPicker = (NumberPicker) getDialog().findViewById(R.id.hour_picker);
    minPicker = (NumberPicker) getDialog().findViewById(R.id.min_picker);

    return super.onCreateDialogView();
}

注意缺少的+ - 控件

screen shot of custom dialog preference

time_preference.xml

<TextView
    android:id="@+id/textView5"
    android:layout_width="wrap_content"
    android:layout_height="38dp"
    android:gravity="bottom"
    android:text="remind every"
    android:textAppearance="?android:attr/textAppearanceMedium" />

<LinearLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" >

    <NumberPicker
        android:id="@+id/hour_picker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hr"
        android:textAppearance="?android:attr/textAppearanceMedium" />

    <NumberPicker
        android:id="@+id/min_picker"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Min"
        android:textAppearance="?android:attr/textAppearanceMedium" />
</LinearLayout>

TimePeriodPreference.java

public class TimePeriodPreference extends DialogPreference {
    int intervalLength = 0;

    public TimePeriodPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        setDialogLayoutResource(R.layout.time_preference);
        setPositiveButtonText(android.R.string.ok);
        setNegativeButtonText(android.R.string.cancel);
        setDialogIcon(null);
        setPersistent(false);
    }

    void setValue(int intervalLength) {
        NumberPicker hourPicker, minPicker;

        hourPicker = (NumberPicker) getDialog().findViewById(R.id.hour_picker);
        short hours = (short) (intervalLength / 60);
        hourPicker.setValue(hours);
        minPicker = (NumberPicker) getDialog().findViewById(R.id.min_picker);
        short minutes = (short) (intervalLength % 60);
        minPicker.setValue(minutes);
    }

    void setDefaultValues() {
        NumberPicker hourPicker, minPicker;

        hourPicker = (NumberPicker) getDialog().findViewById(R.id.hour_picker);
        hourPicker.setMinValue(0);
        hourPicker.setMaxValue(23);
        hourPicker.setValue(0);
        minPicker = (NumberPicker) getDialog().findViewById(R.id.min_picker);
        minPicker.setMinValue(0);
        minPicker.setMaxValue(59);
        minPicker.setValue(0);
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        super.onDialogClosed(positiveResult);
        // When the user selects "OK", persist the new value
        if (positiveResult) {
            NumberPicker hourPicker, minPicker;

            hourPicker = (NumberPicker) getDialog().findViewById(R.id.hour_picker);
            short hours = (short) ((NumberPicker) hourPicker).getValue();
            minPicker = (NumberPicker) getDialog().findViewById(R.id.min_picker);
            short minutes = (short) ((NumberPicker) minPicker).getValue();
            intervalLength = hours * 60 + minutes;
        }
    }

    @Override
    protected View onCreateDialogView() {
        return super.onCreateDialogView();
    }

    @Override
    protected void onSetInitialValue(boolean restorePersistedValue, Object defaultValue) {
            setDefaultValues();
            intervalLength = (Integer) defaultValue;
    }

    /* (non-Javadoc)
     * @see android.preference.DialogPreference#onBindDialogView(android.view.View)
     */
    @Override
    protected void onBindDialogView(View view) {
        super.onBindDialogView(view);
    }
}

EditAlertPreferencesActivity.java

public class EditAlertPreferencesActivity extends Activity {

private static final String DISPLAY_MESSAGE = "display_msg";
private static final String ALERT_TYPE = "alert_type";
private static final String INTERVAL = "interval";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.user_prefs_fragment);

}

// Fragment that displays the mesg preference
public static class UserPreferenceFragment extends PreferenceFragment {

    protected static final String TAG = "REGU";
    private OnSharedPreferenceChangeListener mListener;
    private Preference showMsgPreference;
    private Preference alertTypePreference;
    private Preference intervalPreference;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // Load the preferences from an XML resource
        addPreferencesFromResource(R.xml.user_prefs);

        // Get the msg Preference
        showMsgPreference = (Preference) getPreferenceManager()
                .findPreference(DISPLAY_MESSAGE);
        alertTypePreference = (Preference) getPreferenceManager()
                .findPreference(ALERT_TYPE);
        intervalPreference = (Preference) getPreferenceManager()
                .findPreference(INTERVAL);          
        // Attach a listener to update summary when msg changes
        mListener = new OnSharedPreferenceChangeListener() {
            @Override
            public void onSharedPreferenceChanged(
                    SharedPreferences sharedPreferences, String key) {
                showMsgPreference.setSummary(sharedPreferences.getString(
                        DISPLAY_MESSAGE, "None Set"));
                alertTypePreference.setSummary(sharedPreferences.getString(
                        ALERT_TYPE, "regular intervals or one time"));          
                intervalPreference.setSummary(sharedPreferences.getString(
                        INTERVAL, "-1"));   
            }
        };

        // Get SharedPreferences object managed by the PreferenceManager for
        // this Fragment
        SharedPreferences prefs = getPreferenceManager()
                .getSharedPreferences();

        // Register a listener on the SharedPreferences object
        prefs.registerOnSharedPreferenceChangeListener(mListener);

        // Invoke callback manually to display the msg
        mListener.onSharedPreferenceChanged(prefs, DISPLAY_MESSAGE);
        mListener.onSharedPreferenceChanged(prefs, ALERT_TYPE);
        mListener.onSharedPreferenceChanged(prefs, INTERVAL);

    }

}

}

user_prefs_fragment.xml

    <?xml version="1.0" encoding="utf-8"?>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    class="com.mypreferences.EditAlertPreferencesActivity$UserPreferenceFragment"
    android:orientation="vertical" 
    android:id="@+id/userPreferenceFragment">    
</fragment>

1 个答案:

答案 0 :(得分:2)

When (in which method) should I access the number pickers to harvest the values okay'ed? 

您的TimePeriodPreference课程需要像这样实施DialogInterface.OnClickListenerOverride onClick方法。

Override
public void onClick(DialogInterface dialog, int which){

if(which == DialogInterface.BUTTON_POSITIVE) {
    // do your stuff to handle positive button

 }else if(which == DialogInterface.BUTTON_NEGATIVE){
    // do your stuff to handle negative button
 }
}

然后,您可以在点击Ok按钮(BUTTON_POSITIVE)时访问数字选择器。

编辑:

Why are the number pickers in my custom dialog preference missing the familiar +- controls? 

您需要像这样为选择器设置最大值和最小值,以显示增量和减量值。

NumberPicker np = (NumberPicker)findViewById(R.id.picker);
np.setMaxValue(100);
np.setMinValue(0);

您需要在onCreateDialogView中设置选择器的默认值。只有在这里才会创建对话框视图。

    @Override
protected View onCreateDialogView() {
    View dialogView =  super.onCreateDialogView();
      // set the default values to the view
      NumberPicker hourPicker = (NumberPicker) dialogView.findViewById(R.id.hour_picker);
      hourPicker.setMinValue(0);
      hourPicker.setMaxValue(23);
      return dialogView;
}

注意:getDialog()仅在您显示对话框时才有效。