Home » Android » android – Create NumberPicker dialog in preference

android – Create NumberPicker dialog in preference

Posted by: admin June 15, 2020 Leave a comment

Questions:

I am trying to create a NumberPicker dialog in my preference screen. I have already made one following this:https://stackoverflow.com/a/5533295/2442638

However, for my second dialog, I only want one spinner, so I have adapted the code as follows:

import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.TypedArray;
import android.preference.DialogPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.NumberPicker;

public class SnoozeTPP extends DialogPreference { 

    private int Minute = 0;
    private NumberPicker np= null;

    public static int getMinute(String time) {
        String[] pieces = time.split(":");

        return (Integer.parseInt(pieces[1]));
    }

    public SnoozeTPP(Context context, AttributeSet attrs) {
        super(context, attrs);

        setPositiveButtonText("Set"); 
        setNegativeButtonText("Cancel"); 
    }

    @Override
    protected View onCreateDialogView() {
        np = new NumberPicker(getContext());

        return (np);
    }

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

        np.setMaxValue(60);
        np.setValue(Minute);
    }

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

        if (positiveResult) {

            Minute = np.getValue();

            String time = 0 + ":" + String.valueOf(Minute);

            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("08:00");
            } else {
                time = getPersistedString(defaultValue.toString());
            }
        } else {
            time = defaultValue.toString();
        }

        Minute = getMinute(time);
    }

}

There are no errors and the dialog pops up correctly, but the layout of it seems to be “messed up” :-). The blue line stretch across the whole dialog instead of just the width of the numbers. enter image description here

The question is – how to set the layout correctly? (I am sure there are lots of other mistakes as well!)

Thank you

How to&Answers:

I solved this by using the CyanogenMod number picker.
Java file:

https://github.com/CyanogenMod/android_packages_apps_Trebuchet/blob/cm-10.2/src/com/cyanogenmod/trebuchet/preference/NumberPickerPreference.java

XML file:
https://github.com/CyanogenMod/android_packages_apps_Trebuchet/blob/cm-10.2/res/layout/number_picker_dialog.xml

Attributes:
https://github.com/CyanogenMod/android_packages_apps_Trebuchet/blob/cm-10.2/res/values/attrs.xml#L158

Answer:

Here is an example of simple, but working NumberPickerPreference, saving integer value between 1 and 100:

app screenshot

NumberPickerPreference.java:

public class NumberPickerPreference extends DialogPreference {
    private NumberPicker mPicker;
    private Integer mNumber = 0;

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

    public NumberPickerPreference(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        setPositiveButtonText(android.R.string.ok);
        setNegativeButtonText(android.R.string.cancel);
    }

    @Override
    protected View onCreateDialogView() {
        mPicker = new NumberPicker(getContext());
        mPicker.setMinValue(1);
        mPicker.setMaxValue(100);
        mPicker.setValue(mNumber);
        return mPicker;
    }

    @Override
    protected void onDialogClosed(boolean positiveResult) {
        if (positiveResult) {
            // needed when user edits the text field and clicks OK
            mPicker.clearFocus();
            setValue(mPicker.getValue());
        }
    }   

    @Override
    protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
        setValue(restoreValue ? getPersistedInt(mNumber) : (Integer) defaultValue);
    }

    public void setValue(int value) {
        if (shouldPersist()) {
            persistInt(value);
        }

        if (value != mNumber) {
            mNumber = value;
            notifyChanged();
        }
    }

    @Override
    protected Object onGetDefaultValue(TypedArray a, int index) {
        return a.getInt(index, 0);
    }
}

Answer:

This is more a workaround than a solution, but i hope it helps. Adding a dummy textView solved the problem. I got exactly the same problem.

My xml File:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/textDummyEmpty"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/textDummyEmpty" />

    <NumberPicker 
        android:id="@+id/numberPicker1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" /> 

</LinearLayout>

and

android:text="@string/textDummyEmpty" 

is an empty String. Maybe its also enough to use just a view instead of a textView.

Answer:

return a LinearLayout in onCreateDialogView rather than NumberPicker as below:

@Override
protected View onCreateDialogView() {
    numberPicker = new NumberPicker(getContext());
    numberPicker.setMinValue(1);
    numberPicker.setMaxValue(12);
    numberPicker.setWrapSelectorWheel(false);
    numberPicker.setValue(lastValue);

    LinearLayout.LayoutParams pickerParams = new LinearLayout.LayoutParams
            (LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    pickerParams.gravity = Gravity.CENTER;
    numberPicker.setLayoutParams(pickerParams);

    LinearLayout layout = new LinearLayout(getContext());
    LinearLayout.LayoutParams params = new LinearLayout.LayoutParams
            (LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
    layout.setOrientation(LinearLayout.VERTICAL);
    layout.setLayoutParams(params);

    layout.addView(numberPicker);
    return layout;

    //return numberPicker;
}