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" />
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(); }
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, ...);