web-dev-qa-db-fra.com

Changement de la couleur du séparateur NumberPicker

Sur les versions récentes d'Android, les sélecteurs nombre utilisent un séparateur bleu lors du tirage (cf. image ci-dessous).

enter image description here

Je voudrais changer cette couleur. Y a-t-il une solution de travail? ou peut-être une bibliothèque qui contient une version mise à jour de NumberPicker qui permet de personnaliser la couleur du séparateur?

J'ai essayé Android-numberpicker mais je reçois une erreur (voir ci-dessous) à l'exécution à cause d'un code de la bibliothèque qui tente d'accéder à un identifiant de ressource inexistant.

Android.content.res.Resources$NotFoundException: Resource ID #0x0
        at Android.content.res.Resources.getValue(Resources.Java:1123)
        at Android.content.res.Resources.loadXmlResourceParser(Resources.Java:2309)
        at Android.content.res.Resources.getLayout(Resources.Java:939)
        at Android.view.LayoutInflater.inflate(LayoutInflater.Java:395)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.Java:635)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.Java:560)
        at net.simonvt.numberpicker.NumberPicker.<init>(NumberPicker.Java:550)
30
Laurent

Basé sur ceci ( https://stackoverflow.com/a/20291416/2915480 bien qu'il s'agisse de DatePicker), il y a plusieurs façons:

  1. Écrivez votre propre NumberPicker sans mSelectionDivider et ses filiales, ni utilisez le port backporté par Vikram . Dans le dernier cas: 

    1. télécharger depuis lib à partir de github
    2. change dessable dans res/drawable-xxx/np_numberpicker_selection_divider.9.png:

      • transparent (ou autre) .9.png 
      • créez une ressource de ligne de forme np_numberpicker_selection_divider.xml en format res/dessinable (avec 0dp hauteur ou couleur transparente).
    3. OU supprimez la branche if (mSelectionDivider != null) de la méthode onDraw (Canvas) dans NumberPicker.Java like here

  2. Utilisez la réflexion pour accéder à private final field mSelectionDivider (détails: https://github.com/Android/platform_frameworks_base/blob/master/core/Java/Android/widget/NumberPicker.Java ) - p. Ex. voir modification ici . J'ai utilisé la réflexion mais ce n'est pas la meilleure solution. 

18

Si vous voulez simplement changer la couleur (en fonction de la réponse de stannums)

private void setDividerColor(NumberPicker picker, int color) {

    Java.lang.reflect.Field[] pickerFields = NumberPicker.class.getDeclaredFields();
    for (Java.lang.reflect.Field pf : pickerFields) {
        if (pf.getName().equals("mSelectionDivider")) {
            pf.setAccessible(true);
            try {
                ColorDrawable colorDrawable = new ColorDrawable(color);
                pf.set(picker, colorDrawable);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (Resources.NotFoundException e) {
                e.printStackTrace();
            }
            catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            break;
        }
    }
}

Et après ça

setDividerColor(mNumberPicker, Color.GREEN);
59
gabin

Cela a fonctionné pour moi sans utiliser le reflet. 

my_layout.xml

<NumberPicker
   ...
   Android:theme="@style/DefaultNumberPickerTheme" />

Styles.xml (AppTheme est le thème de mon application dans l'application)

<style name="DefaultNumberPickerTheme" parent="AppTheme">
        <item name="colorControlNormal">@color/dividerColor</item>
</style>
30
Rubin Yoo

J'utilise la méthode de contournement Java:

  private void setDividerColor (NumberPicker picker) {   

        Java.lang.reflect.Field[] pickerFields = NumberPicker.class.getDeclaredFields();
        for (Java.lang.reflect.Field pf : pickerFields) {
            if (pf.getName().equals("mSelectionDivider")) {
                pf.setAccessible(true);
                try {
                    //pf.set(picker, getResources().getColor(R.color.my_orange));
                    //Log.v(TAG,"here");
                    pf.set(picker, getResources().getDrawable(R.drawable.dot_orange));
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (NotFoundException e) {
                    e.printStackTrace();
                } 
                catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                break;
            }
        }
        //}
     }

ou méthode Kotlin:

private fun NumberPicker.setDividerColor(color: Int) {
    val dividerField = NumberPicker::class.Java.declaredFields.firstOrNull { it.name == "mSelectionDivider" } ?: return
    try {
       dividerField.isAccessible = true
       dividerField.set(this,getResources().getDrawable(R.drawable.dot_orange))
    } catch (e: Exception) {
        e.printStackTrace()
    }
}

Et appliquer ses

  setDividerColor(yourNumberPicker); // for Java method
  yourNumberPicker.setDividerColor(Color.RED) // for kotlin method
10
stannums

Comme je suis assez nouveau sur Android, n'oubliez pas que cette solution n'est peut-être pas une bonne pratique, mais j'ai trouvé un moyen (hacky) d'obtenir cet effet en utilisant uniquement XML/SANS réflexion.

J'ai été en mesure de "changer" les couleurs des séparateurs de mes NumberPickers dans LinearLayout en ajoutant 2 minces vues horizontales au ViewGroup et en leur donnant des marges de mise en page négatives ainsi que la couleur souhaitée pour leurs arrière-plans: 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
    Android:orientation="horizontal"
    Android:layout_gravity="center_horizontal"
    Android:gravity="center"
    Android:layout_width="wrap_content"
    Android:layout_height="wrap_content"
    >
    <NumberPicker
        Android:layout_width="70dip"
        Android:layout_height="wrap_content"
        Android:focusable="true"
        Android:focusableInTouchMode="true"
        Android:layout_gravity="center"
        Android:layout_margin="5dp"
        />

    <View
        Android:layout_height="2dp"
        Android:layout_width="70dp"
        Android:background="@color/myColor"
        Android:layout_gravity="center_vertical"
        Android:layout_marginLeft="-75dp"
        Android:layout_marginBottom="-25dp">

    </View>

    <View
        Android:layout_height="2dp"
        Android:layout_width="70dp"
        Android:background="@color/myColor"
        Android:layout_gravity="center_vertical"
        Android:layout_marginLeft="-70dp"
        Android:layout_marginBottom="25dp">

    </View>

</LinearLayout>

Certes, je ne change pas la couleur, mais j'ajoute de nouvelles lignes avec la couleur souhaitée au-dessus des séparateurs intégrés. Espérons que cela aide quelqu'un quand même!

Vous devrez peut-être jouer avec les marges, mais ces paramètres étaient parfaits pour ma boîte de dialogue personnalisée. 

3
JDune

Vous pouvez utiliser la réflexion pour faire l'affaire. Voici ma solution

public class ColorChangableNumberPicker extends NumberPicker {

    public ColorChangableNumberPicker(Context context) {
        super(context);
        init();
    }

    public ColorChangableNumberPicker(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public ColorChangableNumberPicker(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    @TargetApi(Build.VERSION_CODES.Lollipop)
    public ColorChangableNumberPicker(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
        init();
    }

    private void init() {
        setDividerColor(Color.RED);
    }


    public void setDividerColor(@ColorInt int color) {
        try {
            Field fDividerDrawable = NumberPicker.class.getDeclaredField("mSelectionDivider");
            fDividerDrawable.setAccessible(true);
            Drawable d = (Drawable) fDividerDrawable.get(this);
            d.setColorFilter(color, PorterDuff.Mode.SRC_ATOP);
            d.invalidateSelf();
            postInvalidate(); // Drawable is dirty
        }
        catch (Exception e) {

        }
    }
}
2
Bojan Kseneman

J'utilise le code ci-dessous pour changer le séparateur, pas directement la couleur, mais vous pouvez le faire avec un png comme ceci .

Cette solution que je vous apporte vient de ici , mais mon code est une simplification facile pour changer le diviseur et c'est tout. 

    // change divider
    Java.lang.reflect.Field[] pickerFields = NumberPicker.class
            .getDeclaredFields();
    for (Java.lang.reflect.Field pf : pickerFields) {
        if (pf.getName().equals("mSelectionDivider")) {
            pf.setAccessible(true);
            try {
                pf.set(spindle, getResources().getDrawable(R.drawable.np_numberpicker_selection_divider_green));
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (NotFoundException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            break;
        }
    }
1
SerSánGal

C'est facile avec ma bibliothèque (j'ai aussi lancé mon propre NumberPicker). 

<com.github.tomeees.scrollpicker.ScrollPicker
    ...
    app:selectorColor="..."
    />
0
Tamás Sajti

Il est préférable de stocker un champ privé si vous souhaitez modifier la couleur du séparateur à l'avenir. Comme ça:

@Nullable private Field dividerField;

public void setDivider(@Nullable Drawable divider) {
    try {
        if (dividerField == null) {
            dividerField = NumberPicker.class.getDeclaredField("mSelectionDivider");
            dividerField.setAccessible(true);
        }

        dividerField.set(this, divider);
    } catch (Exception ignore) {}
}
0
0neel

en utilisant ce code pour tout ce que vous voulez faire avec diviseur 

Field[] pickerFields = NumberPicker.class.getDeclaredFields();
            for (Field pf : pickerFields) {
                if (pf.getName().equals("mSelectionDivider")) {
                    pf.setAccessible(true);
                    try {
                        pf.set(picker, getResources().getDrawable(R.drawable.divider));
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (NotFoundException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                    break;
                }
            }
0
Alireza Taghizadeh