102 votes

Comment référencer les attributs de style depuis un drawable?

Je veux avoir 2 thèmes sélectionnables pour mon application. Pour ce faire, j'ai défini certains attributs, comme ceci :

Ensuite, j'ai créé les deux thèmes, comme ceci :

     <item name="item_background">#123456</item>

     <item name="item_background">#ABCDEF</item>

Cette méthode fonctionne très bien, me permettant de créer et de modifier plusieurs thèmes facilement. Le problème est que il semble que cela ne puisse être utilisé que dans les vues, et non dans les dessins.

Par exemple, référencer une valeur à partir d'une vue à l'intérieur d'une mise en page fonctionne :

Mais faire la même chose dans un dessin ne fonctionne pas :

Je reçois cette erreur lors de l'exécution de l'application :

    java.lang.UnsupportedOperationException: Can't convert to color: type=0x2

Si au lieu de ?item_background j'utilise une couleur codée en dur, cela fonctionne, mais cela ne me permet pas d'utiliser mes thèmes. J'ai également essayé ?attr:item_background, mais le même problème se produit.

Comment pourrais-je faire cela ? Et pourquoi cela fonctionne dans les vues mais pas dans les dessins ? Je ne trouve pas cette limitation dans la documentation...

179voto

resus Points 1910

Dans mon expérience, il n'est pas possible de référencer un attribut dans un XML drawable.
Pour créer votre thème, vous devez :

  • Créer un XML drawable par thème.
  • Inclure la couleur nécessaire directement dans votre drawable avec la balise @color ou au format #RGB.

Créer un attribut pour votre drawable dans attrs.xml.

Ajouter votre drawable à votre theme.xml.

   <item name="my_drawable">@drawable/my_drawable</item>

Référencer votre drawable dans votre mise en page en utilisant votre attribut.

20voto

marmor Points 4559

À partir de lollipop (API 21), cette fonctionnalité est prise en charge, voir https://code.google.com/p/android/issues/detail?id=26251

Cependant, si vous ciblez des appareils sans lollipop, ne l'utilisez pas, car cela provoquera un crash, utilisez plutôt la solution de contournement dans la réponse acceptée.

5voto

rubo Points 344

Bien qu'il ne soit pas possible de référencer les attributs de style à partir de dessins sur les appareils pre-Lollipop, il est possible pour les listes d'états de couleur. Vous pouvez utiliser la méthode AppCompatResources.getColorStateList(Context context, int resId) de la bibliothèque de support Android. L'inconvénient est que vous devrez définir ces listes d'états de couleur de manière programmatique.

Voici un exemple très basique.

color/my_color_state.xml

Un widget qui a besoin d'une liste d'états de couleur :

Et le plus important :

ColorStateList csl = AppCompatResources.getColorStateList(context, R.color.my_color_state);    
RadioButton r = (RadioButton) findViewById(R.id.radio_button);
r.setTextColor(csl);

Eh bien, ce n'est pas la manière la plus élégante ou la plus courte, mais c'est ce que la bibliothèque de support Android fait pour le faire fonctionner sur les anciennes versions (pre-Lollipop) d'Android.

Malheureusement, la méthode similaire pour les dessins ne fonctionne pas avec les attributs de style.

5voto

Pol Points 18

J'ai répondu à la même question dans https://stackoverflow.com/a/59467269/3841352 mais je vais aussi la poster ici :

J'ai rencontré le même problème et en 2019, il n'a pas été résolu, donc vous ne pouvez pas avoir un attribut référencé dans un sélecteur en tant que drawable. Je vais partager la solution que j'ai trouvée pour le problème car je ne le vois pas affiché ici. Je l'ai trouvé dans le dernier commentaire du rapport de bug.

La solution de contournement consiste essentiellement à créer une ressource drawable qui sera celle qui référencera la valeur de l'attribut.

Pour illustrer votre cas, la solution serait plutôt que :

vous remplaceriez le ?attr/* par une ressource drawable :

Les drawables seraient définis comme suit :

drawable/colorPrimaryDrawable

drawable/colorPrimaryDarkDrawable

J'espère que cela vous aidera !!

0voto

Benjamin Points 564

Comme @marmor l'a dit, c'est maintenant pris en charge sur API 21. Mais pour ceux d'entre nous qui ont besoin de prendre en charge des versions antérieures d'Android, vous pouvez utiliser cette fonctionnalité. En utilisant la bibliothèque de support v7, vous pouvez toujours l'utiliser sur des applications ayant un niveau SDK minimum jusqu'à 7.

Le AppCompatImageView dans la bibliothèque de support v7 Android a une implémentation sans bug de cette fonctionnalité. Remplacez simplement vos utilisations de ImageView par AppCompatImageView.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X