63

Is there a way to set the minimum, maximum and default values of a NumberPicker from the XML Layout?

I'm doing it from within the Activity code:

np = (NumberPicker) findViewById(R.id.np);
np.setMaxValue(120);
np.setMinValue(0);
np.setValue(30);

XML is obviously more appropriate , because it defines property, not behaviour.

Is there a way to set these using the XML layout?

Adam Matan
  • 128,757
  • 147
  • 397
  • 562
  • 3
    You might need to Customize NumberPicker and then use it MyNumberPicker everywhere...and in the Constructor of MyNumberPicker get all attribute set and set values... – MKJParekh Sep 07 '12 at 13:02
  • @MKJParekh do you know how to set setMaxValue setMinValue for Time picker? http://stackoverflow.com/questions/20188983/how-to-set-the-setmaxvalue-setminvalue-for-time-picker-dailog-fragment – LOG_TAG Nov 25 '13 at 10:01

3 Answers3

60

I had the same problem, this is how I solved it (according to the comment of MKJParekh):

  1. I created my own NumberPicker-Class

    package com.exaple.project;
    
    import android.annotation.TargetApi;
    import android.content.Context;
    import android.os.Build;
    import android.util.AttributeSet;
    import android.widget.NumberPicker;
    
    @TargetApi(Build.VERSION_CODES.HONEYCOMB)//For backward-compability
    public class MyNumberPicker extends NumberPicker {
    
        public MyNumberPicker(Context context) {
            super(context);
        }
    
        public MyNumberPicker(Context context, AttributeSet attrs) {
            super(context, attrs);
            processAttributeSet(attrs);
        }
    
        public MyNumberPicker(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
            processAttributeSet(attrs);
        }
        private void processAttributeSet(AttributeSet attrs) {
            //This method reads the parameters given in the xml file and sets the properties according to it
            this.setMinValue(attrs.getAttributeIntValue(null, "min", 0));
            this.setMaxValue(attrs.getAttributeIntValue(null, "max", 0));
        }
    }
    
  2. Now you can use this NumberPicker in your xml layout file

    <com.exaple.project.myNumberPicker
        android:id="@+id/numberPicker1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical"
        max="100"
        min="1" />
    

Thanks to MKJParekh for his useful comment

Defuera
  • 5,356
  • 3
  • 32
  • 38
MazeChaZer
  • 1,228
  • 14
  • 8
  • 4
    Works great, thanks for sharing. Pay attention when using the graphical layout editor in Eclipse: if you change anything here, the custom properties like min and max will get deleted and you have to add them manually again. – pgruetter May 13 '14 at 20:15
  • 3
    Note that it is good to define the custom XML attributes in `res/values/attrs.xml` as described in the [docs](https://developer.android.com/training/custom-views/create-view.html#customattr). This also enables IDEs / layout editors to recognize the custom attributes. The docs also say the `AttributeSet` shouldn't be used directly (as here), instead one should retrieve a `TypedArray`. – user905686 Sep 21 '16 at 21:24
  • Thanks for sharing. Very surprised Google "forgot" to place these fundamental properties into the base class. – TomDK Aug 21 '19 at 03:46
  • thanks a lot, you can also override setValue so you can set inside XML file. – Mohamed AbdelraZek Nov 04 '19 at 18:29
  • @MazeChaZer - I think [my answer](https://stackoverflow.com/a/48219853/2957169) should just be a comment under yours. If you want to merge it into your answer, then I will delete mine. – charles-allen Oct 18 '21 at 00:26
10

You can try this:

<NumberPicker
  android:id="@+id/number_picker"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  app:minValue="@{0}"
  app:maxValue="@{120}"
  app:value="@{30}"/>

This works as part of Android Databinding. So, you might want to set it to true in your app level build.gradle.

android {
    ...

    dataBinding {
        enabled true
    }
}
Namitha Reval
  • 551
  • 1
  • 7
  • 13
7

Here is an updated version that follows the Android Docs
(and thus supports theming & Android Studio designer preview)

values/attrs.xml:

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

    <declare-styleable name="NumberPickerWithXml">
        <attr name="maxValue" format="integer" />
        <attr name="minValue" format="integer" />
        <attr name="defaultValue" format="integer" />
    </declare-styleable>

</resources>

NumberPickerWithXml.kt:

package com.example.library.ui

import android.content.Context
import android.util.AttributeSet
import android.widget.NumberPicker
import com.example.library.ui.R

class NumberPickerWithXml : NumberPicker {

    constructor(context: Context) : super(context)

    constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
        processXmlAttributes(attrs)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        processXmlAttributes(attrs, defStyleAttr)
    }

    constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) {
        processXmlAttributes(attrs, defStyleAttr, defStyleRes)
    }

    private fun processXmlAttributes(attrs: AttributeSet, defStyleAttr: Int = 0, defStyleRes: Int = 0) {
        val attributes = context.theme.obtainStyledAttributes(attrs, R.styleable.NumberPickerWithXml, defStyleAttr, defStyleRes)

        try {
            this.minValue = attributes.getInt(R.styleable.NumberPickerWithXml_minValue, 0)
            this.maxValue = attributes.getInt(R.styleable.NumberPickerWithXml_maxValue, 0)
            this.value = attributes.getInt(R.styleable.NumberPickerWithXml_defaultValue, 0)
        } finally {
            attributes.recycle()
        }
    }

}

...or NumberPickerWithXml.java (untested):

package com.example.library.ui

import android.content.Context;
import android.util.AttributeSet;
import android.widget.NumberPicker;
import com.example.library.ui.R;

public class NumberPickerWithXml extends NumberPicker {

    public NumberPickerWithXml(Context context) {
        super(context);
    }

    public NumberPickerWithXml(Context context, AttributeSet attrs) {
        super(context, attrs);
        processXmlAttributes(attrs, 0, 0);
    }

    public NumberPickerWithXml(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        processXmlAttributes(attrs, defStyleAttr, 0);
    }

    public NumberPickerWithXml(Context context, AttributeSet attrs, int: defStyleAttr, int: defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        processXmlAttributes(attrs, defStyleAttr, defStyleRes);
    }

    private void processXmlAttributes(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        TypedArray attributes = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.NumberPickerWithXml, defStyleAttr, defStyleRes);

        try {
            this.setMinValue(attributes.getInt(R.styleable.NumberPickerWithXml_minValue, 0));
            this.setMaxValue(attributes.getInt(R.styleable.NumberPickerWithXml_maxValue, 0));
            this.setValue(attributes.getInt(R.styleable.NumberPickerWithXml_defaultValue, 0));
        } finally {
            attributes.recycle();
        }
    }

}

Usage in your layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:custom="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools">

    <com.example.library.ui.NumberPickerWithXml
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        custom:defaultValue="30"
        custom:maxValue="120"
        custom:minValue="0" />

</LinearLayout>
Abandoned Cart
  • 4,512
  • 1
  • 34
  • 41
charles-allen
  • 3,891
  • 2
  • 23
  • 35
  • A super easy way to verify your Java code would be to throw it in a Java file in Android Studio. It would have pointed out all of the errors really fast. – Abandoned Cart Oct 16 '21 at 23:19
  • 1
    @AbandonedCart - Thanks for fixing it! The Java version was a bit of an after-thought; it didn't cross my mind that I could just add a Java file to my pure Kotlin project! On reflection today, I think my answer should just be a comment under MazeChaZer's answer. – charles-allen Oct 18 '21 at 00:21
  • Personally, I preferred this one. It was much more complete and easier to follow, both of which may have been lost as a comment. – Abandoned Cart Oct 18 '21 at 01:31
  • I'll keep it up until it becomes obsolete :) – charles-allen Oct 18 '21 at 05:20