Change the text color of NumberPicker
The solution I tried and worked for me is:
In styles.xml add:
<style name="AppTheme.Picker" parent="Theme.AppCompat.Light.NoActionBar" >
<item name="android:textColorPrimary">@android:color/black</item>
</style>
Then use it like this inside your layout:
<NumberPicker
android:id="@+id/dialogPicker"
android:theme="@style/AppTheme.Picker"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="15dp" />
Not sure why you would need to dive into Java Reflection API for this. Its a simple styling matter. The attribute that you need to override is: textColorPrimary
.
<style name="AppTheme" parent="@android:style/Theme.Holo.Light">
....
<item name="android:textColorPrimary">#ff0000</item>
</style>
If you're using the TimePicker
inside a Dialog
, override android:textColorPrimary
in the dialog's theme.
That's about it.
Additional info:
Here's an insightful comment by Yoann Hercouet:
This solution does not change only the color on the NumberPicker, it is a global change that will impact A LOT of components
This is correct, but it overlooks the possibilities I am hinting at. Moreover, global
implies app-wide impact. That can be limited to activity-scope by applying this theme only to activities containing the NumberPicker
. But, I agree, this may still be too corrosive.
The idea here is to somehow inject textColorPrimary=INTENDED_COLOR
into the theme that will be seen by NumberPicker
. There are multiple ways to achieve this. Here's one way:
Define a bare-bone style in res/values/styles.xml
:
<style name="NumberPickerTextColorStyle">
<item name="android:textColorPrimary">@color/intended_color</item>
</style>
Now, create a custom NumberPicker
:
public class ThemedNumberPicker extends NumberPicker {
public ThemedNumberPicker(Context context) {
this(context, null);
}
public ThemedNumberPicker(Context context, AttributeSet attrs) {
// wrap the current context in the style we defined before
super(new ContextThemeWrapper(context, R.style.NumberPickerTextColorStyle), attrs);
}
}
Finally, use ThemedNumberPicker
in your layout(s):
<package.name.ThemedNumberPicker
android:id="@+id/numberPicker"
....
....
.... />
We have successfully contained the impact that textColorPrimary=INTENDED_COLOR
has on our app.
This is of course just one option. For example, if you were inflating a layout containing a NumberPicker
, you could use:
// In this case, the layout contains <NumberPicker... />, not <ThemedNumberPicker... />
LayoutInflater.from(new ContextThemeWrapper(context, R.style.NumberPickerTextColorStyle))
.inflate(R.layout.number_picker_layout, ...);
This code should solve your problem. The problem you are experiencing is because during the construction of NumberPicker it captures the EditText textColor and assigns to to a paint so it can draw the numbers above and below the edit text with the same color.
import java.lang.reflect.Field;
public static void setNumberPickerTextColor(NumberPicker numberPicker, int color)
{
try{
Field selectorWheelPaintField = numberPicker.getClass()
.getDeclaredField("mSelectorWheelPaint");
selectorWheelPaintField.setAccessible(true);
((Paint)selectorWheelPaintField.get(numberPicker)).setColor(color);
}
catch(NoSuchFieldException e){
Log.w("setNumberPickerTextColor", e);
}
catch(IllegalAccessException e){
Log.w("setNumberPickerTextColor", e);
}
catch(IllegalArgumentException e){
Log.w("setNumberPickerTextColor", e);
}
final int count = numberPicker.getChildCount();
for(int i = 0; i < count; i++){
View child = numberPicker.getChildAt(i);
if(child instanceof EditText)
((EditText)child).setTextColor(color);
}
numberPicker.invalidate();
}