改变 TimePicker 文字颜色

12
我一直在尝试更改时间选择器的文本颜色。但是我找不到父级样式所在的位置。我已经尝试了以下两种方法
<style name="MyTimePicker" parent="@android:style/Widget.Holo.TimePicker">
    <item name="android:textColor">@color/text</item>
</style>

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

我的minSdkVersion是15。我的targetSdkVersion是20。我已经重新构建并清理了我的项目。
我认为我已经查看了Stack Overflow上的每一个类似问题,但是它们都没有真正为我提供解决方案。唯一可能起作用的答案是使用某种库,但我不太喜欢那个解决方案。路径到父级是否与我正在使用的路径不同,因为我相信我应该可以以某种方式访问它?

编辑
这是主题应用的方式;

<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" />

关于这个错误,以下是我收到的错误提示(之前忘记放了):

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

编辑2 我看过一些问题来尝试解决这个问题:

  1. 如何覆盖 TimePicker 以更改文本颜色 - 我认为这个问题已经接近答案了,但我不完全确定我需要做什么?我需要将 Android TimePicker 样式导入到我的项目中吗?
  2. https://stackoverflow.com/questions/24973586/set-textcolor-for-timepicker-in-customized-app-theme - 没有给出答案。
  3. 如何更改我的 TimePicker 和 DatePicker 的文本颜色? - 尝试了 0 票的答案,但它不起作用。
  4. 如何在 Android 中更改 DatePicker 和 TimePicker 对话框的默认颜色? - 再次无法以类似的方式找到 TimePicker。
  5. Android - 如何更改 TimePicker 中的文本颜色? - 同样,找不到实际的 TimePicker 父级。

这些可能是解决我的问题的最佳问题/答案,但它们都没有帮助我。能得到这个问题的明确答案会很好。


第一种样式应该有效,你是怎么应用那个样式的? - pskink
@pskink 更新了答案。 - Bono
尝试过这个了吗? - Simas
@user3249477 是的,我也尝试过那些方法。但是它们都不起作用,因为无法找到TimePicker(我可以找到像actionbar等其他东西)。我可以在android styles.xml中找到这些样式,但我无法访问它们(特别是TimePicker)。 - Bono
1
我已经在这里回答了这个问题:https://dev59.com/kGAg5IYBdhLWcg3w9fDm#22962195 - Simon
7个回答

25

我结合了Paul Burke的答案Simon的答案,成功地编辑了TimePicker的文本颜色。

实现方法如下:

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);
        }
    }
}
请注意,这个答案可能已经过时了。我之前遇到了一个可能存在问题的东西(请参阅我的问题以获取更多详细信息)。否则,您应该按照Vikram的回答来进行操作。

1
java.lang.NullPointerException: 尝试在空对象引用上调用虚拟方法'int android.widget.NumberPicker.getChildCount()'. 最终,计数 = number_picker.getChildCount(); - void pointer
@voidpointer 如果您有其他问题,请使用屏幕右上角的“提问”按钮。您遇到的是普通的空指针异常。 - Bono
2
@Bono 这段代码在安卓棒棒糖上无法运行。hour_numberpicker以及其他所有都只返回null,仅限于安卓棒棒糖系统。 - Abhinav singh
@Bono 尝试了同样的方法来改变文本大小。但是当我们滚动更改时间时,大小会恢复到原始大小。 - Sahana Prabhakar
1
请注意,此答案可能已过时。 - Bono
自API 29开始,NumberPicker有setTextColor()函数,因此不需要再绕过这个问题了。 - undefined

9

不确定为什么需要深入了解Java反射API。这只是一个简单的样式问题。您需要覆盖的属性是:textColorPrimary

<style name="AppTheme" parent="@android:style/Theme.Holo.Light">
    ....
    <item name="android:textColorPrimary">#ff0000</item>
</style>

如果您正在Dialog中使用TimePicker,请在对话框主题中覆盖android:textColorPrimary

就这样。


问题在于它找不到Theme.Holo.Light的父级。这就是为什么文本颜色无法更改的原因。不幸的是,您的答案与有些不同。我很快会考虑编辑我的问题来表达这一点。 - Bono
@Bono 不确定为什么它找不到 Theme.Holo.Light。但是这里的父级无关紧要。你应该保持父级为你已经使用的任何东西,最可能是 Theme.AppCompat[.Light] - Vikram
@Bono 更多信息:为 TimePicker 提供文本颜色的 attrtextColorPrimary。因此,我们可以通过上述方式覆盖此 attr 来更改文本颜色。但是,此 attr 也用作所有 TextViews 的默认文本颜色。这意味着,如果您 _不提供 android:textColor="@color/some_color"_,它将使用 textColorPrimary。最简单的方法是使用 ContextThemeWrapper 在 Java 中创建 TimePicker。鉴于这个问题很旧了,感谢您的评论。如果您需要使用 ContextThemeWrapper 的工作示例,请告诉我。 - Vikram

5

Vikram 的回答中,需要添加:将主题设置为 timePicker,而不是将其设置为样式。

styles.xml 文件中进行设置。

 <style name="timePickerOrange">
    <item name="android:textColorPrimary">@color/orange</item> <!-- color for digits -->
    <item name="android:textColor">@color/orange</item> <!-- color for colon -->
    <item name="android:colorControlNormal">@color/orange</item> <!-- color for (horizontal) delimeters -->
</style>

并且对于时间选择器

<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" />

这个不起作用。 - alfietap

4
一个TimePicker实际上只是两个NumberPicker。查看Widget.NumberPicker的样式和布局,你会发现它使用了
@style/TextAppearance.Large.Inverse.NumberPickerInputText

很遗憾,TextAppearance.Large.Inverse.NumberPickerInputText 没有使用您可以在主题中设置的属性之一。因此,您有两个选择:

  1. 复制必要的类以创建自己的 NumberPickerTimePicker 版本。(您可以从库中提取一些东西,比如 HoloEverywhere)

  2. 使用 hack。

如果您想走第二条路,可以这样做:

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);
}

编辑

经过进一步调查,这种方法并不是非常有效。它不能让您更改NumberPicker上方/下方数值的颜色。在用户与其交互后,颜色也会重置。似乎您唯一的选择就是创建必要类的副本(上面提到的选项#1)。


谢谢 Paul,"hack" 看起来很好。不过我有几个问题:如何让上下的数字也改变颜色?当我旋转/更改微调器(以选择不同的数字)时,它们会默认回到黑色。我该如何防止这种情况发生? - Bono
@Bono 请查看我的更新答案。看起来选项1可能是正确控制这个问题的唯一方法。 :-( - Paul Burke

2
@Vikram是正确的。 这很简单。你可以尝试这种方式。
<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>

1
你可以尝试设置 android:textColorPrimaryInverseandroid:textColorSecondaryInverse。这样做可以避免使用反射。
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:textColorPrimaryInverse">@android:color/black</item>
    <item name="android:textColorSecondaryInverse">@color/colorLightGrey</item>
</style>

那就是我需要的。 - Ely Dantas

0

对于使用Spinner的人来说,这是一种轻松更改颜色甚至提供前一个和后一个数字的适当阴影效果的方法。Spinner需要一个主题,因为大多数默认的XML颜色属性只影响时钟模式。

styles.xml

  <style name="timepicker">
       <item name="android:textColorSecondary">@color/white </item>
       <item name="android:textColorPrimary">@color/white </item>

    </style>

XML布局文件

 <TimePicker
        android:id="@+id/timePicker1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:theme="@style/timepicker"
        android:layout_below="@id/line1"
        android:layout_centerHorizontal="true"
        android:padding="15dp"
        android:timePickerMode="spinner" />

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接