12

I've been trying to change the textcolor of my timepicker. But I can't find where the parent style is located. I've tried both

<style name="MyTimePicker" parent="@android:style/Widget.Holo.TimePicker">
    <item name="android:textColor">@color/text</item>
</style>

and

<style name="MyTimePicker" parent="@android:style/Widget.TimePicker">
    <item name="android:textColor">@color/text</item>
</style>

My minSdkVersion is 15. My targetSdkVersion is 20. I have rebuilded and cleaned my project.
I think I've been through every similar question on SO and none of them really have provided a solution for me. The only answer that might work is using some sort of library, but I'm not a big fan of that solution. Is the path to the parent something different from what I'm using, because I'm pretty sure I should be able to access it somehow?

Edit
This is how the theme is applied;

<TimePicker
    style="@style/MyTimePicker"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/timePicker"
    android:layout_below="@+id/textView"
    android:layout_centerHorizontal="true" />

On a note this is the error I receive (forgot to place it before):

Error:Error retrieving parent for item: No resource found that matches the given name '@android:style/Widget.Holo.TimePicker'.

Edit 2 A couple of the questions I've viewed to try to solve this:

  1. How can I override TimePicker to change text color - I think this question gets as close to an answer, but I'm not entirely sure what I need to do? Do I need to import the android TimePicker style into my project?
  2. https://stackoverflow.com/questions/24973586/set-textcolor-for-timepicker-in-customized-app-theme - No answer is given.
  3. How can i change the textcolor of my timepicker and datepicker? - Tried the 0 votes answer, but it didn't work.
  4. How to change the default color of DatePicker and TimePicker dialog in Android? - Again can't find the TimePicker in a similar way.
  5. Android - How do I change the textColor in a TimePicker? - Again, can't find the actual TimePicker parent.

These are probably the best questions/answers to my problem, but none of them help me. It would be nice to get a definitive answer on this.

Community
  • 1
  • 1
Bono
  • 4,477
  • 6
  • 43
  • 76
  • the first style should work, how did you applied that style? – pskink Sep 24 '14 at 11:51
  • @pskink updated answer – Bono Sep 24 '14 at 11:56
  • Tried [this](http://stackoverflow.com/a/21361885/3249477)? – Simas Sep 27 '14 at 13:41
  • @user3249477 Yes I tried that/those too. Non of them work, because the TimePicker cannot be found (I can find things such as actionbar etc.). I _can_ find the styles in android styles.xml, but I can't access them (the TimePicker specifically) – Bono Sep 27 '14 at 15:21
  • 1
    I have already answered this question, here: http://stackoverflow.com/questions/22962075/change-the-text-color-of-numberpicker/22962195#22962195 – Simon Sep 28 '14 at 20:23

6 Answers6

25

I have combined Paul Burke's Answer and Simon's Answer to succesfully edit the text colour of the TimePicker.

Here's how it is accomplished:

TimePicker time_picker; //Instantiated in onCreate()
Resources system;

private void set_timepicker_text_colour(){
    system = Resources.getSystem();
    int hour_numberpicker_id = system.getIdentifier("hour", "id", "android");
    int minute_numberpicker_id = system.getIdentifier("minute", "id", "android");
    int ampm_numberpicker_id = system.getIdentifier("amPm", "id", "android");

    NumberPicker hour_numberpicker = (NumberPicker) time_picker.findViewById(hour_numberpicker_id);
    NumberPicker minute_numberpicker = (NumberPicker) time_picker.findViewById(minute_numberpicker_id);
    NumberPicker ampm_numberpicker = (NumberPicker) time_picker.findViewById(ampm_numberpicker_id);

    set_numberpicker_text_colour(hour_numberpicker);
    set_numberpicker_text_colour(minute_numberpicker);
    set_numberpicker_text_colour(ampm_numberpicker);
}

private void set_numberpicker_text_colour(NumberPicker number_picker){
    final int count = number_picker.getChildCount();
    final int color = getResources().getColor(R.color.text);

    for(int i = 0; i < count; i++){
        View child = number_picker.getChildAt(i);

        try{
            Field wheelpaint_field = number_picker.getClass().getDeclaredField("mSelectorWheelPaint");
            wheelpaint_field.setAccessible(true);

            ((Paint)wheelpaint_field.get(number_picker)).setColor(color);
            ((EditText)child).setTextColor(color);
            number_picker.invalidate();
        }
        catch(NoSuchFieldException e){
            Log.w("setNumberPickerTextColor", e);
        }
        catch(IllegalAccessException e){
            Log.w("setNumberPickerTextColor", e);
        }
        catch(IllegalArgumentException e){
            Log.w("setNumberPickerTextColor", e);
        }
    }
}

Please note that this answer might be outdated by now. I ran into this a while ago with something that might have been buggy (see my question for more details). Otherwise you should probably follow Vikram's answer.

einUsername
  • 1,231
  • 2
  • 13
  • 22
Bono
  • 4,477
  • 6
  • 43
  • 76
  • 1
    java.lang.NullPointerException: Attempt to invoke virtual method 'int android.widget.NumberPicker.getChildCount()' on a null object reference. final int count = number_picker.getChildCount(); – void pointer May 18 '15 at 09:05
  • @voidpointer if you have another question please use the "ask question" button on the top right of your screen. What you have is a plain null pointer exception. – Bono May 18 '15 at 09:21
  • 2
    @Bono This code is not work in android Lollipop.. hour_numberpicker ya other all is given by null only for Android Lollipop.. – Abhinav singh Jun 25 '15 at 09:35
  • @Bono Tried the same thing for changing text size. But when we scroll to change the time, the size changes to the original size. – Sahana Prabhakar Jan 18 '18 at 06:57
  • Note that this answer may be outdated currently. – Bono Mar 05 '19 at 11:18
7

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.

Vikram
  • 49,828
  • 11
  • 86
  • 118
  • The problem is it couldn't find the `Theme.Holo.Light` parent. That's why the text color couldn't be changed. Unfortunately your answer is about something a bit different. I'll look to editing my question soon to portray this. – Bono Apr 29 '15 at 14:28
  • @Bono Not sure why it can't find `Theme.Holo.Light`. But the parent is irrelevant here. You should keep the parent as whatever you are already using, most probably `Theme.AppCompat[.Light]`. – Vikram Apr 29 '15 at 22:04
  • @Bono A bit more info: the `attr` that supplies the text color for `TimePicker` is `textColorPrimary`. So, we can change the text color by overriding this attr as above. BUT, this attr is also used as the default text color for all `TextViews`. Meaning, if you _don't supply an `android:textColor="@color/some_color"`_, it will use `textColorPrimary`. The easiest way to go about this is to create the `TimePicker` in java using a `ContextThemeWrapper`. Seeing that this question is quite old, I appreciate your comment. Do let me know if you need a working example using `ContextThemeWrapper`. – Vikram Apr 29 '15 at 23:41
4

A TimePicker is really just two NumberPickers. Looking into the Widget.NumberPicker style and layout, you'll find the it uses

@style/TextAppearance.Large.Inverse.NumberPickerInputText

Unfortunately, TextAppearance.Large.Inverse.NumberPickerInputText doesn't use one of the attributes that you can set in your theme. So you have two options:

  1. Copy the necessary classes to make your own version of NumberPicker and TimePicker. (You might be able to extract something from libraries like HoloEverywhere)

  2. Use hacks.

If you want to go the second route, you can do this:

private int mNumberPickerInputId = 0;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    Resources system = Resources.getSystem();

    // This is the internal id of the EditText used in NumberPicker (hack)
    mNumberPickerInputId = 
        system.getIdentifier("numberpicker_input", "id", "android");

    // just used for full example, use your TimePicker
    TimePicker timePicker = new TimePicker(this);
    setContentView(timePicker);

    final int hourSpinnerId = 
        system.getIdentifier("hour", "id", "android");
    View hourSpinner = timePicker.findViewById(hourSpinnerId);
    if (hourSpinner != null) {
        setNumberPickerTextColor(hourSpinner, Color.BLUE);
    }

    final int minSpinnerId = 
        system.getIdentifier("minute", "id", "android");
    View minSpinner = timePicker.findViewById(minSpinnerId);
    if (minSpinner != null) {
        setNumberPickerTextColor(minSpinner, Color.BLUE);
    }

    final int amPmSpinnerId = 
        system.getIdentifier("amPm", "id", "android");
    View amPmSpinner = timePicker.findViewById(amPmSpinnerId);
    if (amPmSpinner != null) {
        setNumberPickerTextColor(amPmSpinner, Color.BLUE);
    }
}

private void setNumberPickerTextColor(View spinner, int color) {
    TextView input = (TextView) spinner.findViewById(mNumberPickerInputId);
    input.setTextColor(color);
}

EDIT

Upon further investigation, this hack doesn't really work well. It won't allow you to change the color of the NumberPicker above/below values. The color also resets after the use interacts with it. It seems that your only option will be to create your own copies of the necessary classes (option #1 above).

Paul Burke
  • 24,988
  • 9
  • 63
  • 61
  • Thanks Paul the "hack" looks fine to me. I have a couple of questions though; How do I get the numbers above and below to change colours as well? And when I rotate/change the spinners (to pick a different number) they default back to black again. How do I prevent this? – Bono Sep 27 '14 at 16:06
  • @Bono Please see my updated answer. Looks like option 1 may be the only way to properly control this. :-( – Paul Burke Sep 27 '14 at 22:34
2

Adding to Vikram answer , Set the theme to timePicker do not set it as style

in styles.xml

 <style name="timePickerOrange">
    <item name="android:textColorPrimary">@color/orange</item>
    <item name="android:textColor">@color/orange</item>
</style>

and for timePicker

<TimePicker
    android:theme="@style/timePickerOrange"
    android:id="@+id/timePicker_defaultTime"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:fontFamily="@font/hero_regular"
    android:timePickerMode="spinner"
    app:fontFamily="@font/hero_regular" />
Manohar Reddy
  • 15,894
  • 7
  • 77
  • 109
1

@Vikram is right This is so simple.You can try this way

<style name="abirStyle" parent="@android:style/Theme.Holo.Light.Dialog.NoActionBar">
    <item name="android:textColor">@color/colorPrimary</item>
    <item name="android:background">@null</item>
    <item name="android:textColorPrimary">@color/colorPrimary</item>
</style>
Muhaiminur Rahman
  • 2,459
  • 17
  • 22
1

You can try to set android:textColorPrimaryInverse and android:textColorSecondaryInverse. That should do the job without using Reflection.

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:textColorPrimaryInverse">@android:color/black</item>
    <item name="android:textColorSecondaryInverse">@color/colorLightGrey</item>
</style>
mkruglikov
  • 56
  • 5