50

On recent android versions, number pickers use a blue divider when drawn (cf. image below).

enter image description here

I would like to change this color. Is there a working solution? or perhaps a library that package an updated version of NumberPicker that allows customizing the divider color?

I have tried android-numberpicker but I get an error (see below) at runtime due to some code from the library that tries to access to a resource id that does not exist.

android.content.res.Resources$NotFoundException: Resource ID #0x0
        at android.content.res.Resources.getValue(Resources.java:1123)
        at android.content.res.Resources.loadXmlResourceParser(Resources.java:2309)
        at android.content.res.Resources.getLayout(Resources.java:939)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:395)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.java:635)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.java:560)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.java:550)
Laurent
  • 14,122
  • 13
  • 57
  • 89
  • Does this answer your question?: http://stackoverflow.com/questions/18804762/change-android-numberpicker-divider-color – eikooc Jun 15 '14 at 19:57
  • No, it's not working. First answer that aims to create a custom style is not working because symbol '@style/Holo.NumberPicker' cannot be resolved. For the second answer, the result is the same: calling set(numberPicker, color) on field mSelectionDivider retrieved by reflection has no effect. – Laurent Jun 15 '14 at 20:15

13 Answers13

72

This worked for me without using the reflection.

my_layout.xml

<NumberPicker
   ...
   android:theme="@style/DefaultNumberPickerTheme" />

Styles.xml (AppTheme is my app theme in the app)

<style name="DefaultNumberPickerTheme" parent="AppTheme">
        <item name="colorControlNormal">@color/dividerColor</item>
</style>
Rubin Yoo
  • 2,674
  • 2
  • 24
  • 32
  • 9
    Just a friendly reminder. 'colorControlNormal', only works for API 21 and above. – Jcorretjer Jan 12 '18 at 23:28
  • 1
    please suggest an alternative to 'colorControlNormal' if one exists – BiGGZ Apr 18 '18 at 18:01
  • 1
    Just want to point out that using `colorControlNormal` didn't work for me and I had to explicitly add the `android:` prefix, like so `#ffffff` – hannojg Dec 08 '21 at 12:47
61

If you want simply to change the color (based on stannums answer):

private void setDividerColor(NumberPicker picker, int color) {

    java.lang.reflect.Field[] pickerFields = NumberPicker.class.getDeclaredFields();
    for (java.lang.reflect.Field pf : pickerFields) {
        if (pf.getName().equals("mSelectionDivider")) {
            pf.setAccessible(true);
            try {
                ColorDrawable colorDrawable = new ColorDrawable(color);
                pf.set(picker, colorDrawable);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (Resources.NotFoundException e) {
                e.printStackTrace();
            }
            catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            break;
        }
    }
}

And after that

setDividerColor(mNumberPicker, Color.GREEN);
gabin
  • 927
  • 1
  • 10
  • 20
  • 3
    Nice change. One thing I noticed is to be sure to use 'newColorDrawable(ctx.getResources().getColor(R.color.whatevercolor))' instead of 'new ColorDrawable(R.color.whatevercolor)' – easycheese Apr 25 '15 at 16:54
  • 1
    I really think, that it should mark as a try answer! It is really simple and work! – Sirop4ik May 02 '16 at 15:19
  • It might be better: `ColorDrawable colorDrawable = new ColorDrawable(ContextCompat.getColor(getContext(), R.color.primaryColor));` – Hesam Apr 11 '17 at 19:41
  • Thanks mate! I translated this into a Kotlin Extension and its working perfectly. – Lucas P. Dec 09 '20 at 14:56
29

Based on this (https://stackoverflow.com/a/20291416/2915480 although it's about DatePicker) there are several ways:

  1. Write your own NumberPicker without mSelectionDivider and its affiliates or use backported by Vikram. In last case:
  2. download from lib from github
  3. change drawable in res/drawable-xxx/np_numberpicker_selection_divider.9.png:
  • to transparent (or whatever) .9.png * create np_numberpicker_selection_divider.xml shape line resource in res/drawable (with 0dp height or transparent color).
  1. OR remove if (mSelectionDivider != null) branch from onDraw(Canvas) method in NumberPicker.java like here

  2. Use reflection to access private final field mSelectionDivider (details: https://github.com/android/platform_frameworks_base/blob/master/core/java/android/widget/NumberPicker.java) - e.g. see modification here. I used reflection but it's not the best solution.

  3. Use theming to override the number picker's divider color in API 21+: ?attr/colorControlNormal determines the color of the divider in material number picker, so changing this color in your widget's theme will do the trick, e.g. for DatePicker:

    <style name="MyAppTheme.NumberPicker" parent=" MyAppTheme">
        <item name="android:colorControlNormal"> ?colorAccent </item>
    </style>

and in the widget:

 <DatePicker
        android:id="@+id/question_date"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" 
        android:calendarViewShown="false"
        android:datePickerMode="spinner"
        android:gravity="center"
        android:theme="@style/MyAppTheme.NumberPicker" />
Pascal
  • 15,257
  • 2
  • 52
  • 65
Margarita Litkevych
  • 2,086
  • 20
  • 28
  • Thank you for your help. Solution 2 works perfectly but I failed to make solution 1 work. For this last, resource id associated to variable DEFAULT_LAYOUT_RESOURCE_ID in NumberPicker.java seems to be no longer valid. Last but not least, my goal was to change color to a custom one and not to hide dividers. To achieve this goal I haven't set `mSelectionDivider` to `null` but equals to a drawable which is a simple nine patch PNG loaded with `getResources().getDrawable(R.drawable.np_numberpicker_selection_divider)` – Laurent Jun 21 '14 at 04:13
15

I'm use workaround Java method:

  private void setDividerColor (NumberPicker picker) {   

        java.lang.reflect.Field[] pickerFields = NumberPicker.class.getDeclaredFields();
        for (java.lang.reflect.Field pf : pickerFields) {
            if (pf.getName().equals("mSelectionDivider")) {
                pf.setAccessible(true);
                try {
                    //pf.set(picker, getResources().getColor(R.color.my_orange));
                    //Log.v(TAG,"here");
                    pf.set(picker, getResources().getDrawable(R.drawable.dot_orange));
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (NotFoundException e) {
                    e.printStackTrace();
                } 
                catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
        //}
     }

or Kotlin method:

private fun NumberPicker.setDividerColor(color: Int) {
    val dividerField = NumberPicker::class.java.declaredFields.firstOrNull { it.name == "mSelectionDivider" } ?: return
    try {
       dividerField.isAccessible = true
       dividerField.set(this,getResources().getDrawable(R.drawable.dot_orange))
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

And apply its

  setDividerColor(yourNumberPicker); // for java method
  yourNumberPicker.setDividerColor(Color.RED) // for kotlin method
stannums
  • 342
  • 5
  • 5
3

Actually you can change the color of divider writing a custom theme.

As an example add this to your themes.xml

<style name="NumberPickerTheme" parent="Theme.AppCompat.Light">
        <item name="colorAccent">@android:color/white</item>
        
        <!-- Edit this colorControlNormal value as you need -->
        <item name="colorControlNormal">@android:color/holo_green_dark</item>
        
        <item name="android:textColorPrimary">@android:color/black</item>
        <item name="android:background">@android:color/white</item>
        <item name="android:textSize">30sp</item>
    </style>

And Add this theme to your Numberpicker

<NumberPicker
        android:id="@+id/index_picker1"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:theme="@style/NumberPickerTheme"
         />

If you want to get rid of dividers just use

<item name="colorControlNormal">@android:color/transparent</item>
Sachin Das
  • 319
  • 3
  • 8
2

You can use reflection to do the trick. Here is my solution

public class ColorChangableNumberPicker extends NumberPicker {

    public ColorChangableNumberPicker(Context context) {
        super(context);
        init();
    }

    public ColorChangableNumberPicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ColorChangableNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    public ColorChangableNumberPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        setDividerColor(Color.RED);
    }


    public void setDividerColor(@ColorInt int color) {
        try {
            Field fDividerDrawable = NumberPicker.class.getDeclaredField("mSelectionDivider");
            fDividerDrawable.setAccessible(true);
            Drawable d = (Drawable) fDividerDrawable.get(this);
            d.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
            d.invalidateSelf();
            postInvalidate(); // Drawable is dirty
        }
        catch (Exception e) {

        }
    }
}
Bojan Kseneman
  • 15,488
  • 2
  • 54
  • 59
  • I think this is the best ansewr. Also I think this is too mucho for just customizing a single line... But that's system fault. You helped me a lot. Thanks – Sierisimo Mar 03 '16 at 07:53
2

I'm fairly new to Android so bear in mind that this solution may not be a good practice, but I found a (hacky) way to get this effect using only XML / WITHOUT reflection.

I was able to 'change' the colors of the dividers on my NumberPickers within a LinearLayout by adding 2 thin, horizontal views to the ViewGroup, and giving them negative layout margins and my desired color for their backgrounds:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_gravity="center_horizontal"
    android:gravity="center"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    >
    <NumberPicker
        android:layout_width="70dip"
        android:layout_height="wrap_content"
        android:focusable="true"
        android:focusableInTouchMode="true"
        android:layout_gravity="center"
        android:layout_margin="5dp"
        />

    <View
        android:layout_height="2dp"
        android:layout_width="70dp"
        android:background="@color/myColor"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="-75dp"
        android:layout_marginBottom="-25dp">

    </View>

    <View
        android:layout_height="2dp"
        android:layout_width="70dp"
        android:background="@color/myColor"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="-70dp"
        android:layout_marginBottom="25dp">

    </View>

</LinearLayout>

Admittedly, I'm not actually changing the color, but adding new lines with my desired color on top of the built-in dividers. Hopefully this helps someone anyway!

You may have to play with the margins, but these settings were perfect for my custom dialog.

Necreaux
  • 9,451
  • 7
  • 26
  • 43
JDune
  • 567
  • 7
  • 10
  • sorry this is not a valid solution, to play with margin and elevation or what ever, to hide elements in back of an other view :) – issamux Jun 16 '22 at 21:35
1

I use the below code to change the divider, not directly the color, but you can do that with a png like this.

This solution that I bring you comes from here, but my code is a easy simplification to change the divider and that's it.

    // change divider
    java.lang.reflect.Field[] pickerFields = NumberPicker.class
            .getDeclaredFields();
    for (java.lang.reflect.Field pf : pickerFields) {
        if (pf.getName().equals("mSelectionDivider")) {
            pf.setAccessible(true);
            try {
                pf.set(spindle, getResources().getDrawable(R.drawable.np_numberpicker_selection_divider_green));
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (NotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            break;
        }
    }
Community
  • 1
  • 1
SerSánGal
  • 467
  • 4
  • 15
1

It's easy with my library (I rolled my own NumberPicker too).

<com.github.tomeees.scrollpicker.ScrollPicker
    ...
    app:selectorColor="..."
    />
Tamás Sajti
  • 53
  • 1
  • 7
0

using this code for evry thing u want do with divider

Field[] pickerFields = NumberPicker.class.getDeclaredFields();
            for (Field pf : pickerFields) {
                if (pf.getName().equals("mSelectionDivider")) {
                    pf.setAccessible(true);
                    try {
                        pf.set(picker, getResources().getDrawable(R.drawable.divider));
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (NotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
Reza Taghizadeh
  • 347
  • 5
  • 11
0

It's better to store a private field if you are going to change divider color in future. Like this:

@Nullable private Field dividerField;

public void setDivider(@Nullable Drawable divider) {
    try {
        if (dividerField == null) {
            dividerField = NumberPicker.class.getDeclaredField("mSelectionDivider");
            dividerField.setAccessible(true);
        }

        dividerField.set(this, divider);
    } catch (Exception ignore) {}
}
0neel
  • 383
  • 5
  • 11
0

Kotlin

You can change divider number in this way without version control. This example set transparent color:

private fun setDividerColor(picker: NumberPicker) {
    val dividerField = NumberPicker::class.java.declaredFields.firstOrNull { it.name == "mSelectionDivider" } ?: return
    try {
        val colorDrawable = ColorDrawable(android.graphics.Color.TRANSPARENT)
        dividerField.isAccessible = true
        dividerField.set(picker, colorDrawable)
    } catch (e: Exception) {
        e.printStackTrace()
    }
}
canerkaseler
  • 6,204
  • 45
  • 38
-5

simplest way is to add this attribute in you NumberPicker selector in xml

android:selectionDivider="@colors/your_color"
msamardzic
  • 1,060
  • 9
  • 12