Изменение цвета текста NumberPicker

Я посмотрел почти все темы об этом и никто не дал ответа. Стиль NumberPicker не работает (в соответствии с этим потоком:NumberPicker textColour)

Установка атрибута style на numberPicker в стиль, который имеет элемент цвета, также не имеет никакого эффекта. Также Установка атрибута textColor в XML numberPicker ничего не делает.

ближе всего к этому я использую numberPicker, чтобы бросить его getChildAt () в EditText, а затем сделать setColor () на этом EditText, но это только изменяет цвет ребенка один раз при инициализации, а затем каждый раз, когда он выбран из него; не то, что я ищу либо.

помочь? Спасибо

8 ответов


этот код должен решить вашу проблему. Проблема, которую вы испытываете, заключается в том, что во время построения NumberPicker он захватывает EditText textColor и назначает краске, чтобы она могла рисовать числа выше и ниже текста редактирования с тем же цветом.

import java.lang.reflect.Field;

public static boolean setNumberPickerTextColor(NumberPicker numberPicker, int color)
{
    final int count = numberPicker.getChildCount();
    for(int i = 0; i < count; i++){
        View child = numberPicker.getChildAt(i);
        if(child instanceof EditText){
            try{
                Field selectorWheelPaintField = numberPicker.getClass()
                    .getDeclaredField("mSelectorWheelPaint");
                selectorWheelPaintField.setAccessible(true);
                ((Paint)selectorWheelPaintField.get(numberPicker)).setColor(color);
                ((EditText)child).setTextColor(color);
                numberPicker.invalidate();
                return true;
            }
            catch(NoSuchFieldException e){
                Log.w("setNumberPickerTextColor", e);
            }
            catch(IllegalAccessException e){
                Log.w("setNumberPickerTextColor", e);
            }
            catch(IllegalArgumentException e){
                Log.w("setNumberPickerTextColor", e);
            }
        }
    }
    return false;
}

решение, которое я пробовал и работал для меня:

в стилях.добавьте XML-код:

<style name="AppTheme.Picker" parent="Theme.AppCompat.Light.NoActionBar" >
    <item name="android:textColorPrimary">@android:color/black</item>
</style>

затем используйте его так внутри своего макета:

  <NumberPicker
    android:id="@+id/dialogPicker"
    android:theme="@style/AppTheme.Picker"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="15dp" />

не уверен, почему вам нужно будет погрузиться в API отражения Java для этого. Его простой стиль дело. Атрибут, который необходимо переопределить:textColorPrimary.

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

если вы используете TimePicker внутри Dialog, переопределить android:textColorPrimary в теме диалога.

вот и все.

дополнительная информация:

вот проницательный комментарий Йоанн Hercouet:

этот решение не изменяет только цвет на NumberPicker, оно это глобальное изменение, которое повлияет на множество компонентов

это правильно, но он упускает из виду возможности, на которые я намекаю. Более того,global подразумевает влияние на все приложения. Это может быть ограничено областью действия, применяя эту тему только к действиям, содержащим NumberPicker. Но, я согласен, это все еще может быть слишком въедливый.

идея в том, чтобы как-то впрыснуть textColorPrimary=INTENDED_COLOR в тему, которая будет рассматриваться NumberPicker. Существует множество способов добиться этого. Вот один из способов:

определить стиль голой кости в res/values/styles.xml:

<style name="NumberPickerTextColorStyle">
    <item name="android:textColorPrimary">@color/intended_color</item>
</style>

Теперь создайте пользовательский 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);
    }
}

наконец, использовать ThemedNumberPicker в вашем макете(ах):

<package.name.ThemedNumberPicker
    android:id="@+id/numberPicker"
    ....
    ....
    .... />

мы успешно сдержали воздействие, которое textColorPrimary=INTENDED_COLOR на наше приложение.

это, конечно, только один вариант. Например, если вы надували макет содержащий NumberPicker, вы могли бы использовать:

// In this case, the layout contains <NumberPicker... />, not <ThemedNumberPicker... />
LayoutInflater.from(new ContextThemeWrapper(context, R.style.NumberPickerTextColorStyle))
    .inflate(R.layout.number_picker_layout, ...);

вот фрагмент Xamarin из ответа выше с TextSize и TextStyle Bold

public static bool SetNumberPickerTextColorAndSize(NumberPicker numberPicker, Color color, ComplexUnitType complexUnitType, float textSize, TypefaceStyle style)
    {
        int count = numberPicker.ChildCount;
        for (int i = 0; i < count; i++)
        {
            View child = numberPicker.GetChildAt(i);
            if (child.GetType() == typeof(EditText))
            {
                try
                {
                    Field selectorWheelPaintField = numberPicker.Class
                                                                .GetDeclaredField("mSelectorWheelPaint");
                    selectorWheelPaintField.Accessible = true;

                    EditText editText = (EditText) child;
                    editText.SetTextSize(complexUnitType, textSize);
                    editText.SetTypeface(editText.Typeface, style);
                    editText.SetTextColor(color);

                    Paint paint = (Paint) selectorWheelPaintField.Get(numberPicker);
                    paint.TextSize =  TypedValue.ApplyDimension(complexUnitType, textSize, numberPicker.Resources.DisplayMetrics);
                    paint.Color = color;
                    paint.SetTypeface(editText.Typeface);

                    numberPicker.Invalidate();
                    return true;
                }
                catch (NoSuchFieldException e)
                {
                    Log.Warn("setNumberPickerTextColor", e);
                }
                catch (IllegalAccessException e)
                {
                    Log.Warn("setNumberPickerTextColor", e);
                }
                catch (IllegalArgumentException e)
                {
                    Log.Warn("setNumberPickerTextColor", e);
                }
            }
        }
        return false;
    }

принятый ответ слишком сложен. Гораздо более простой подход, который работал для меня, чтобы переопределить: textColorPrimary атрибут темы, которую я использовал.

<style name="Theme.MyTheme" parent="@android:style/Theme.Holo.NoActionBar.Fullscreen" >
        <item name="android:textColorPrimary">#000000</item>
</style>

он сделал работу довольно хорошо!


вместо изменения каждого цвета текста на цвет, который вы хотите, лучше просто изменить весь цвет editText. NumberPicker фактически имеет дочерний EditText, который отображает числа.

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
        <!-- Change edit color here. -->
        <item name="android:editTextColor">#000000</item>
</style>

это сработало для меня. И хотя у меня есть белый текст в кнопках, они не изменились.


Я принял решение @Andreas Merz и обновил свой код. То, как все было назначено, и функции подписи/вызовы, которые он использовал, не были найдены. Я использую min API 19. Вот код, который сработал для меня.

/**
 * Based on https://stackoverflow.com/a/26657169/2313889
 * @param picker
 * @param color
 * @param unit
 * @param textSize
 * @param typeface
 * @return
 */
private void formatNumberPickerText(NumberPicker picker, int color,
                                    int unit, float textSize,
                                    Typeface typeface) {
    int count = picker.getChildCount();
    for (int i = 0; i < count; i++) {
        View child = picker.getChildAt(i);
        if (child instanceof EditText) {
            try {
                Class clazz = picker.getClass();
                Field field = clazz.getDeclaredField("mSelectorWheelPaint");
                field.setAccessible(true);

                EditText editText = (EditText) child;
                editText.setTextSize(unit, textSize);
                editText.setTypeface(typeface);
                editText.setTextColor(color);

                Paint paint = (Paint) field.get(picker);
                paint.setTextSize(TypedValue.applyDimension(
                        unit, textSize, getResources().getDisplayMetrics()
                ));
                paint.setColor(color);
                paint.setTypeface(typeface);

                picker.invalidate();
                return;

            } catch (IllegalAccessException | NoSuchFieldException e) {
                e.printStackTrace();
            }
        }
    }
}

это легко с моим NumberPicker библиотека.

<com.github.tomeees.scrollpicker.ScrollPicker
    ...
    app:textColor="..."
    />