web-dev-qa-db-fra.com

Android: Comment mettre à jour le sélecteur (StateListDrawable) par programme

Je souhaite mettre à jour le sélecteur d'un bouton par programme.

Je peux le faire avec le fichier xml qui est donné ci-dessous

<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
   <item Android:state_enabled="false"
         Android:drawable="@drawable/btn_off" />
   <item Android:state_pressed="true"
         Android:state_enabled="true" 
         Android:drawable="@drawable/btn_off" />
   <item Android:state_focused="true"
         Android:state_enabled="true" 
         Android:drawable="@drawable/btn_on" />
   <item Android:state_enabled="true" 
         Android:drawable="@drawable/btn_on" />
</selector>

Je veux faire la même chose par programme. J'ai essayé quelque chose comme ci-dessous

private StateListDrawable setImageButtonState(int index)
{
    StateListDrawable states = new StateListDrawable();

    states.addState(new int[] {Android.R.attr.stateNotNeeded},R.drawable.btn_off); 
    states.addState(new int[] {Android.R.attr.state_pressed, Android.R.attr.state_enabled},R.drawable.btn_off);
    states.addState(new int[] {Android.R.attr.state_focused, Android.R.attr.state_enabled},R.drawable.btn_on);
    states.addState(new int[] {Android.R.attr.state_enabled},R.drawable.btn_on);

    return states;
}

mais cela n'a pas fonctionné.

Et comment définir Android:state_enabled="false" ou Android:state_enabled="true" par programmation.

60
Mani

Vous devez utiliser la valeur négative de l'état requis. Par exemple.:

states.addState(new int[] {-Android.R.attr.state_enabled},R.drawable.btn_disabled);

Remarquez le signe "-" avant Android.R.attr.state_enabled.

112
Osi

Réponse très tardive ici, mais au cas où quelqu'un d'autre aurait des problèmes à définir un StateListDrawable par programme. Ensuite, comme pour les fichiers XML, l'ordre dans lequel vous définissez les états dans StateListDrawable est important.

Par exemple, cela fonctionnera comme prévu:

StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] { Android.R.attr.state_pressed }, new ColorDrawable(Color.GRAY));
sld.addState(new int[] {}, new ColorDrawable(Color.GREEN));

Cela ne va pas:

StateListDrawable sld = new StateListDrawable();
sld.addState(new int[] {}, new ColorDrawable(Color.GREEN));
sld.addState(new int[] { Android.R.attr.state_pressed }, new ColorDrawable(Color.GRAY));
8
Brett Cherrington

Pas assez de représentant pour commenter mais la réponse acceptée n'a pas fonctionné pour moi.

Mon objectif était que les concepteurs définissent les couleurs d'arrière-plan activées, désactivées et pressées sur un bouton. Je voulais qu'ils l'utilisent pour tester les couleurs sur différents écrans.

J'ai remarqué que d'autres personnes ont mentionné que cela ne fonctionnait pas non plus pour eux.

Les états à définir sont

  • pas enfoncé et activé, c'est ce que vous voyez lorsque le bouton est activé et non enfoncé.
  • pressé et activé, c'est ce que vous voyez lorsque le bouton est enfoncé et activé
  • pas activé. Voici ce que vous voyez lorsque le bouton est désactivé

Voici un code qui vous donnera une idée des états. J'utilise Color.Parse () pour générer des entiers pour les couleurs, puis je les passe à cette méthode pour obtenir le StateListDrawable.

private StateListDrawable createDrawable(int enabled, int pressed, int disabled) {
  StateListDrawable stateListDrawable = new StateListDrawable();

  stateListDrawable.addState(new int[] { -Android.R.attr.state_pressed, Android.R.attr.state_enabled }, new ColorDrawable(enabled));
  stateListDrawable.addState(new int[] { Android.R.attr.state_pressed, Android.R.attr.state_enabled }, new ColorDrawable(pressed));
  stateListDrawable.addState(new int[] { -Android.R.attr.state_enabled }, new ColorDrawable(disabled));

  return stateListDrawable;
}
6
Voski

Je vais répondre à votre question "Comment mettre à jour le sélecteur d'un BOUTON par programmation?" en proposant de changer un bouton pour un LinearLayout avec ImageView et TextView intégrés. Cela présente un certain nombre d'avantages, surtout si vous décidez plus tard de personnaliser vos vues. Il n'y a aucune perte de fonctionnalité résultant de ce commutateur. Vous pourrez toujours attacher les mêmes écouteurs d'événements que vous pouvez attacher à un bouton, mais vous pourrez éviter que les boutons/onglets ne stylisent les cauchemars. Voici un code pertinent du layout.xml

    <LinearLayout 
        Android:id="@+id/button"
        style="@style/ButtonStyle">
        <ImageView 
            Android:id="@+id/background"
            Android:src="@drawable/custom_image"/>
        <TextView 
            style="@style/TextStyle"
            Android:text="Custom Button"
            Android:id="@+id/text"/>
    </LinearLayout> 

Ensuite, j'ai un fichier de sélection appelé custom_image.xml situé dans le dossier drawable. Voici le contenu du fichier sélecteur

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <item Android:drawable="@drawable/disabled_img"     Android:state_enabled="false" />
    <item Android:drawable="@drawable/unselected_img"     Android:state_selected="false" />
    <item Android:drawable="@drawable/selected_img"     Android:state_selected="true" />
</selector>

Les trois fichiers image source (disabled_img.png, unselected_img.png, selected_img.png) se trouvent également dans le dossier dessinable.

Maintenant, revenons à votre Java. Il n'y a pas besoin de la poubelle funky StateListDrawable pour de nombreuses raisons. Tout d'abord, elle a l'air moche et est difficile à maintenir. Mais surtout cela va à l'encontre des principes de séparation de votre logique de votre présentation. Si vous gérez vos ressources dessinables en Java, vous savez que vous faites quelque chose de fondamentalement mauvais.

Voici ce que je propose à la place. Chaque fois que vous voulez que votre bouton soit sélectionné, vous insérez simplement cette doublure:

((LinearLayout)findViewById(R.id.button)).setSelected(true);

Ou chaque fois que vous souhaitez que le bouton soit désactivé, voici une autre ligne unique:

((ImageView)findViewById(R.id.background)).setEnabled(false);

Veuillez noter que dans ce dernier exemple, je spécifie l'état désactivé sur l'ImageView à l'intérieur du LinearLayout. Pour une raison quelconque, chaque fois que vous modifiez l'état activé/désactivé du LinearLayout, le sélecteur n'est pas déclenché. Cela fonctionne bien lorsque vous le faites sur ImageView à la place.

4
Temperage

Je ne sais pas comment vous ajoutez le StateListDrawable, car le code n'est pas ici. Mais assurez-vous de vérifier la documentation et l'ajout de setState().

Vous pouvez définir les propriétés de la vue, telles que yourView.setEnabled(true)

J'espère que ça aide

0
raukodraug