web-dev-qa-db-fra.com

Remplacer les images de sélecteur par programme

J'ai un ImageView qui a une ressource d'image dessinable définie à un sélecteur. Comment est-ce que j'accède par programme au sélecteur et modifie les images de l'état en surbrillance et non en surbrillance?

Voici un code de sélecteur:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:Android="http://schemas.Android.com/apk/res/Android" Android:id="@+id/iconSelector">
  <!-- pressed -->
  <item Android:state_pressed="true" Android:drawable="@drawable/btn_icon_hl" />
  <!-- focused -->
  <item Android:state_focused="true" Android:drawable="@drawable/btn_icon_hl" />
  <!-- default -->
  <item Android:drawable="@drawable/btn_icon" />
</selector>

Je veux pouvoir remplacer btn_icon_hl et btn_icon avec d'autres images.

115
dropsOfJupiter

Pour autant que j'ai pu trouver (j'ai essayé de faire quelque chose de similaire moi-même), il n'y a aucun moyen de modifier un seul état après que StateListDrawable a déjà été défini. Vous pouvez cependant définir un nouveau code via:

StateListDrawable states = new StateListDrawable();
states.addState(new int[] {Android.R.attr.state_pressed},
    getResources().getDrawable(R.drawable.pressed));
states.addState(new int[] {Android.R.attr.state_focused},
    getResources().getDrawable(R.drawable.focused));
states.addState(new int[] { },
    getResources().getDrawable(R.drawable.normal));
imageView.setImageDrawable(states);

Et vous pouvez simplement en garder deux sous la main ou en créer un différent selon vos besoins.

244
kcoppock

J'ai eu le même problème et je suis allé plus loin pour le résoudre. Le seul problème, cependant, est que vous ne pouvez pas spécifier NavStateListDrawable en XML. Vous devez donc définir l’arrière-plan de votre élément d’interface utilisateur par le biais du code. La méthode onStateChange doit ensuite être remplacée pour garantir que, chaque fois que le niveau de la dessinable principale soit modifié, vous mettez également à jour le niveau de la liste des niveaux enfants.

Lors de la construction de NavStateListDrawable, vous devez indiquer le niveau de l'icône que vous souhaitez afficher.

public class NavStateListDrawable extends StateListDrawable {

    private int level;

    public NavStateListDrawable(Context context, int level) {

        this.level = level;
        //int stateChecked = Android.R.attr.state_checked;
        int stateFocused = Android.R.attr.state_focused;
        int statePressed = Android.R.attr.state_pressed;
        int stateSelected = Android.R.attr.state_selected;

        addState(new int[]{ stateSelected      }, context.getResources().getDrawable(R.drawable.nav_btn_pressed));
        addState(new int[]{ statePressed      }, context.getResources().getDrawable(R.drawable.nav_btn_selected));
        addState(new int[]{ stateFocused      }, context.getResources().getDrawable(R.drawable.nav_btn_focused));

        addState(new int[]{-stateFocused, -statePressed, -stateSelected}, context.getResources().getDrawable(R.drawable.nav_btn_default));


    }

    @Override
    protected boolean onStateChange(int[] stateSet) {

        boolean nowstate = super.onStateChange(stateSet);

        try{
            LayerDrawable defaultDrawable = (LayerDrawable)this.getCurrent();


            LevelListDrawable bar2 =  (LevelListDrawable)defaultDrawable.findDrawableByLayerId(R.id.nav_icons);
            bar2.setLevel(level);
        }catch(Exception exception)
        {

        }

        return nowstate;
    }
}

Pour tous les états de boutons de navigation différents, j'ai quelque chose comme ce qui suit.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:Android="http://schemas.Android.com/apk/res/Android">

   <item Android:drawable="@drawable/top_bar_default" >

   </item>

    <item Android:id="@+id/nav_icons" Android:bottom="0dip">
        <level-list xmlns:Android="http://schemas.Android.com/apk/res/Android">
            <item Android:maxLevel="0" >
                <bitmap
                    Android:src="@drawable/top_bar_icon_back"
                    Android:gravity="center" />
            </item>
            <item Android:maxLevel="1" >
                <bitmap
                    Android:src="@drawable/top_bar_icon_nav"
                    Android:gravity="center" />
            </item>
            <item Android:maxLevel="2" >
                <bitmap
                    Android:src="@drawable/top_bar_icon_settings"
                    Android:gravity="center" />
            </item>
            <item Android:maxLevel="3" >
                <bitmap
                    Android:src="@drawable/top_bar_icon_search"
                    Android:gravity="center" />
            </item>
        </level-list>

    </item>

</layer-list>

J'allais publier ceci sous forme de question et de réponse, mais vu que vous avez posé la question, voilà. Notez que cela vous épargne beaucoup de définitions de fichiers XML. Je suis passé d'environ 50-100 définitions XML à environ 4 !.

6
Emile