0

I am trying to use preferences in my UI to get values from the user and to fill into an object. Hence I do not wish to persist them. I created a custom TimePeriodPreference to get a time interval.

1) Why are the number pickers in my custom dialog preference missing the familiar +- controls? Furthermore, they do not allow input of text.

2) When (in which method) should I access the number pickers to harvest the values okay'ed? onDialogClosed() is too late. It gives me a null pointer error as the widgets are apparently lost by then.

    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)

FYI, complete code is here https://www.dropbox.com/s/pul1eximvsfxsvz/DataManagementPreferenceActivity.zip

I followed the steps here: http://developer.android.com/guide/topics/ui/settings.html#Custom

and also here: Concise way of writing new DialogPreference classes?

Trying to move it here following the example here, also causes a null pointer

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

    return super.onCreateDialogView();
}

Note the missing +- controls

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>
Community
  • 1
  • 1
likejudo
  • 3,396
  • 6
  • 52
  • 107

1 Answers1

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

Your TimePeriodPreference class need to implements the DialogInterface.OnClickListener and Override the onClick method like this.

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
 }
}

And then you can access the number picker when the Ok button (BUTTON_POSITIVE) is clicked.

EDIT:

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

You need to set a Max and Minimum value to the picker like this, to display the increment and decrement values.

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

You need to set the default values for the picker in onCreateDialogView. Only here the dialog view will be created.

    @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;
}

Note: getDialog() will be valid only when you show the dialog.

Libin
  • 16,967
  • 7
  • 61
  • 83