NullPointerException
NullPointerException

Reputation: 37635

Is it possible to make a horizontal NumberPicker?

The widget NumberPicker from Android is vertical, with the increase and decrease buttons above and below the number display.

Is it possible to make it horizontal? With the buttons on the left and the right of the number?

Upvotes: 16

Views: 39612

Answers (5)

KnIfER
KnIfER

Reputation: 750

You can make a horizontal NumberPicker out of the defualt vertical NumberPicker, just like that you can make a vertical SeekBar out of the defualt horizontal SeekBar.

To convert a vertical widget to a horizontal one, or to do the reverse, you need to take account of the layout method, of the drawing method and of the touch-control method. However, not all methods are overridable, some of them are private.

To have full control over the widget, you need to write your own widgets based on the defaut one, make the private methods/fields protected, and extend the custom widget to make your modifications.

Here is the ready-to-use horizontal NumberPicker I made two years ago:

enter image description here

source code :

Custom NumberPicker class and Extended Horizontal NumberPicker

Another tall screenshot which shows the usage of both HorizontalNumberPicker and VerticalSeekBar.

Upvotes: 2

stilkin
stilkin

Reputation: 149

I was looking for a similar solution, and created an implementation based on the screenshot in this question. Mind you it is fairly basic and will just allow for integer numbers and setting a minimum and maximum value. (Any extra features you will need to add yourself.)

This is how it will look:

horizontal number picker screenshot

You need a layout file and a class file for the custom component, and then you can use it in your other layout (and class) files.

Layout file: numberpicker_horizontal.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal">

    <Button
        android:id="@+id/btn_less"
        android:layout_width="0sp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:text="-" />

    <EditText
        android:id="@+id/et_number"
        android:layout_width="0sp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:textAlignment="center"
        android:inputType="number"
        android:text="0" />

    <Button
        android:id="@+id/btn_more"
        android:layout_width="0sp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        android:text="+" />
</LinearLayout>

Class file: HorizontalNumberPicker.java

public class HorizontalNumberPicker extends LinearLayout {
    private EditText et_number;
    private int min, max;

    public HorizontalNumberPicker(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);

        inflate(context, R.layout.numberpicker_horizontal, this);

        et_number = findViewById(R.id.et_number);

        final Button btn_less = findViewById(R.id.btn_less);
        btn_less.setOnClickListener(new AddHandler(-1));

        final Button btn_more = findViewById(R.id.btn_more);
        btn_more.setOnClickListener(new AddHandler(1));
    }

    /***
     * HANDLERS
     **/

    private class AddHandler implements OnClickListener {
        final int diff;

        public AddHandler(int diff) {
            this.diff = diff;
        }

        @Override
        public void onClick(View v) {
            int newValue = getValue() + diff;
            if (newValue < min) {
                newValue = min;
            } else if (newValue > max) {
                newValue = max;
            }
            et_number.setText(String.valueOf(newValue));
        }
    }

    /***
     * GETTERS & SETTERS
     */

    public int getValue() {
        if (et_number != null) {
            try {
                final String value = et_number.getText().toString();
                return Integer.parseInt(value);
            } catch (NumberFormatException ex) {
                Log.e("HorizontalNumberPicker", ex.toString());
            }
        }
        return 0;
    }

    public void setValue(final int value) {
        if (et_number != null) {
            et_number.setText(String.valueOf(value));
        }
    }

    public int getMin() {
        return min;
    }

    public void setMin(int min) {
        this.min = min;
    }

    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        this.max = max;
    }
}

Then include it in your other layout files in the following way (replacing com.yourpackage with your own package name):

<com.yourpackage.HorizontalNumberPicker
    android:id="@+id/np_channel_nr"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

You can then use the component like any other component, and use the getValue() method to retrieve the value currently set:

// get a reference to the component
final HorizontalNumberPicker np_channel_nr = dialogView.findViewById(R.id.np_channel_nr);

// use value in your code
final int nr = np_channel_nr.getValue();

Upvotes: 12

milosmns
milosmns

Reputation: 3793

I couldn't find a reliable solution so I made my own in the end, but I needed it to look like a circular cog, so it's adapted for that use case.

You can get the idea from the source though.. Here it is:

https://github.com/milosmns/actual-number-picker

Upvotes: 1

aha
aha

Reputation: 462

Nope. In fact, you can't even really use it yet, even though it appears in the Graphical Layout builder. It's still protected.

This question has some related info: Android Number Picker Dialog

Upvotes: 2

CommonsWare
CommonsWare

Reputation: 1006819

You cannot change NumberPicker AFAIK, but writing your own should be fairly straightforward.

Upvotes: 11

Related Questions