Reputation: 14401
On recent android versions, number pickers use a blue divider when drawn (cf. image below).
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)
Upvotes: 51
Views: 49736
Reputation: 7478
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()
}
}
Upvotes: 0
Reputation: 380
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>
Upvotes: 4
Reputation: 2136
Based on this (https://stackoverflow.com/a/20291416/2915480 although it's about DatePicker) there are several ways:
0dp
height or transparent color).OR remove if (mSelectionDivider != null)
branch from onDraw(Canvas) method in NumberPicker.java like here
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.
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" />
Upvotes: 30
Reputation: 342
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
Upvotes: 15
Reputation: 80
It's easy with my library (I rolled my own NumberPicker too).
<com.github.tomeees.scrollpicker.ScrollPicker
...
app:selectorColor="..."
/>
Upvotes: 1
Reputation: 391
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) {}
}
Upvotes: 0
Reputation: 2720
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>
Upvotes: 74
Reputation: 577
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.
Upvotes: 2
Reputation: 1060
simplest way is to add this attribute in you NumberPicker selector in xml
android:selectionDivider="@colors/your_color"
Upvotes: -5
Reputation: 15668
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) {
}
}
}
Upvotes: 2
Reputation: 477
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;
}
}
Upvotes: 0
Reputation: 924
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);
Upvotes: 60
Reputation: 467
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;
}
}
Upvotes: 1