web-dev-qa-db-fra.com

Changer la couleur du texte de NumberPicker

J'ai regardé la plupart de toutes les discussions à ce sujet et aucune n'a fourni de réponse qui fonctionne. Le style du NumberPicker ne fonctionne pas (selon ce fil: NumberPicker textColour )

La définition de l'attribut style sur le numberPicker sur un style comportant un élément de couleur n'a aucun effet non plus. La définition de l'attribut textColor sur le XML numberPicker ne fait rien non plus.

Le plus proche que j'ai obtenu est d'utiliser le numberPicker pour convertir son getChildAt () en un EditText, puis de définir setColor () sur ce EditText, mais cela ne change la couleur de l'enfant qu'une fois lors de l'initialisation, puis à chaque fois qu'il est sélectionné dans dessus; pas ce que je recherche non plus.

De l'aide? Merci

41
Odaym

Ce code devrait résoudre votre problème. Le problème que vous rencontrez est dû au fait que lors de la construction de NumberPicker, il capture la couleur de texte EditText et l'affecte à une peinture afin qu'il puisse dessiner les numéros au-dessus et en dessous du texte de modification avec la même couleur.

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();  
}
71
Simon

La solution que j'ai essayée et travaillée pour moi est:

Dans styles.xml, ajoutez:

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

Ensuite, utilisez-le comme ceci dans votre mise en page:

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

Vous ne savez pas pourquoi vous devez plonger dans Java API de réflexion pour cela. C'est une question de style simple. L'attribut que vous devez remplacer est: textColorPrimary.

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

Si vous utilisez TimePicker dans un Dialog, remplacez Android:textColorPrimary dans le thème de la boîte de dialogue.

C'est à peu près ça.

Informations supplémentaires:

Voici un commentaire perspicace de Yoann Hercouet :

Cette solution ne change pas seulement la couleur sur le NumberPicker, c'est un changement global qui affectera BEAUCOUP de composants

C'est correct, mais cela néglige les possibilités auxquelles je fais allusion. De plus, global implique un impact à l'échelle de l'application. Cela peut être limité à l'activité-portée en appliquant ce thème uniquement aux activités contenant le NumberPicker. Mais, je suis d'accord, cela peut être encore trop corrosif.

L'idée ici est d'injecter en quelque sorte textColorPrimary=INTENDED_COLOR dans le thème qui sera vu par NumberPicker. Il existe plusieurs façons d'y parvenir. Voici une façon:

Définissez un style à nu dans res/values/styles.xml:

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

Maintenant, créez un NumberPicker personnalisé:

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

Enfin, utilisez ThemedNumberPicker dans votre (vos) disposition (s):

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

Nous avons réussi à contenir l'impact que textColorPrimary=INTENDED_COLOR a sur notre application.

Ce n'est bien sûr qu'une option. Par exemple, si vous gonfliez une mise en page contenant un NumberPicker, vous pourriez utiliser:

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

Voici un extrait Xamarin de la réponse ci-dessus avec TextSize et 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;
    }
7
Andreas Merz

J'ai pris la solution de @ Andreas Merz et mis à jour son code. La façon dont les choses ont été attribuées et les fonctions signatures/appels qu'il a utilisées sont introuvables. J'utilise min API 19. Voici le code qui a fonctionné pour moi.

/**
 * 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();
            }
        }
    }
}
2
Eduardo Reis

Au lieu de changer chaque couleur de texte à la couleur que vous voulez, mieux vaut simplement changer toutes les couleurs editText. NumberPicker a en fait un enfant EditText qui affiche les nombres.

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

Cela a fonctionné pour moi. Et même si j'ai du texte blanc dans les boutons, ils n'ont pas changé.

1
Dinidiniz

La réponse acceptée est trop compliquée. Une approche beaucoup plus simple qui a fonctionné pour moi a été de remplacer l'attribut: textColorPrimary du thème que j'utilisais.

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

Cela a plutôt bien fonctionné!

1
mgm

Pour moi, mettre Android:textColorPrimary dans mon thème n'a rien fait, en regardant le code source du NumberPicker il décide de la couleur du texte de l'entrée EditText donc il faut régler le Android:editTextColor au lieu.

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="Android:editTextColor">@color/dark_gray</item>
</style>
0
Arbitur

Basé sur la réflexion rejetée sur Android SDK> = 29 mieux pour modifier la réponse de Simon:

public void setNumberPickerTextColor(NumberPicker numberPicker, int color){

    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {

        final int count = numberPicker.getChildCount();
        for (int i = 0; i < count; i++) {
            View child = numberPicker.getChildAt(i);
            if (child instanceof EditText) {
                try {
                    ((EditText) child).setTextColor(color);
                    numberPicker.invalidate();

                    Field selectorWheelPaintField = numberPicker.getClass().getDeclaredField("mSelectorWheelPaint");
                    boolean accessible = selectorWheelPaintField.isAccessible();
                    selectorWheelPaintField.setAccessible(true);
                    ((Paint) selectorWheelPaintField.get(numberPicker)).setColor(color);
                    selectorWheelPaintField.setAccessible(accessible);
                    numberPicker.invalidate();

                    Field selectionDividerField = numberPicker.getClass().getDeclaredField("mSelectionDivider");
                    accessible = selectionDividerField.isAccessible();
                    selectionDividerField.setAccessible(true);
                    selectionDividerField.set(numberPicker, null);
                    selectionDividerField.setAccessible(accessible);
                    numberPicker.invalidate();
                } catch (Exception exception) {
                    Logger.exc(exception);
                }
            }
        }
    } else {

        numberPicker.setTextColor(color);
    }
}

Dans le SDK> = 29, NumberPicker a la méthode .setTextColor ().

0
Tapa Save