Ersetzen Sie Selektorbilder programmgesteuert

Lesezeit: 6 Minuten

Ersetzen Sie Selektorbilder programmgesteuert
Tropfen von Jupiter

Ich habe eine ImageView, die eine zeichenbare Bildressource auf einen Selektor gesetzt hat. Wie greife ich programmgesteuert auf den Selektor zu und ändere die Bilder des hervorgehobenen und nicht hervorgehobenen Zustands?

Hier ist ein Auswahlcode:

<?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>

Ich möchte ersetzen können btn_icon_hl und btn_icon mit anderen Bildern.

  • Wäre es nicht einfacher, zwei Selektoren zu haben und sie auszutauschen?

    – große Steine

    15. Januar 2011 um 1:46 Uhr

  • Das Problem dabei ist, dass Sie am Ende Hunderte von XML-Dateien haben können.

    – Emil

    15. Januar 2011 um 14:06 Uhr

Ersetzen Sie Selektorbilder programmgesteuert
Kevin Copock

Soweit ich feststellen konnte (ich habe selbst versucht, etwas Ähnliches zu tun), gibt es keine Möglichkeit, einen einzelnen Status zu ändern, nachdem das StateListDrawable bereits definiert wurde. Sie können jedoch einen NEUEN durch Code definieren:

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

Und Sie können einfach zwei davon zur Hand haben oder bei Bedarf ein anderes erstellen.

  • Ich konnte dies nicht zu einer Bildansicht hinzufügen. setState ist darauf nicht verfügbar.

    – Tropfen von Jupiter

    16. Januar 2011 um 4:32 Uhr

  • tatsächlich habe ich es gefunden, es ist setImageDrawable() Vielen Dank, es hat funktioniert und mir etwa 40 xml-Dateien gespart!

    – Tropfen von Jupiter

    16. Januar 2011 um 4:43 Uhr

  • Dazu habe ich noch eine weitere Anmerkung. Ich hatte gehofft, dass Sie antworten können. Ich habe diesen Selektor auf die ImageView gesetzt, die sich innerhalb des benutzerdefinierten Steuerelements befindet. Das benutzerdefinierte Steuerelement hat auch einen Selektor als Hintergrund. Der Selektor des gesamten Steuerelements funktioniert also, der ImageView-Selektor jedoch nicht. Gibt es etwas, das ich falsch mache? Gibt es eine Reihenfolge?

    – Tropfen von Jupiter

    16. Januar 2011 um 7:15 Uhr


  • Gern geschehen! Ja, ich weiß nicht, warum ich setState gesetzt habe, sollte setImageDrawable sein, du hast Recht. Gemäß Ihrer anderen Frage würde ich vorschlagen, eine neue Frage mit dem Code für Ihr benutzerdefiniertes Steuerelement und seinen Selektor zu posten. Ich bin mir bei der Antwort darauf nicht sicher.

    – Kevin Copock

    16. Januar 2011 um 15:04 Uhr

  • Ich verwende den gleichen Code. immer das bild welches ich angegeben habe in —-> new int[]{} Zustand bleibt. wo lag ich falsch??

    – KK_07k11A0585

    19. Juni 2012 um 12:34 Uhr

Ich hatte das gleiche Problem und ging einen Schritt weiter, um es zu lösen. Das einzige Problem ist jedoch, dass Sie das NavStateListDrawable nicht in XML angeben können, sodass Sie den Hintergrund Ihres UI-Elements durch Code festlegen müssen. Die onStateChange-Methode muss dann überschrieben werden, um sicherzustellen, dass jedes Mal, wenn die Ebene des Haupt-Drawables geändert wird, auch die Ebene der untergeordneten Ebenenliste aktualisiert wird.

Beim Erstellen des NavStateListDrawable müssen Sie die Ebene des Symbols übergeben, das Sie anzeigen möchten.

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

Für all die verschiedenen zeichbaren Zustände der Navigationsschaltfläche habe ich so etwas wie das Folgende.

<?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="https://stackoverflow.com/questions/4697528/@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>

Ich wollte dies als Frage und Antwort posten, aber da Sie genau die Frage gestellt haben, bitte hier. Beachten Sie, dass Sie dadurch eine Menge XML-Dateidefinitionen sparen. Ich ging von ungefähr 50-100 XML-Definitionen auf ungefähr 4 herunter!.

  • Der navstatelistdrawable-Code macht die Selektor-XML effektiv überflüssig.

    – Emil

    15. Januar 2011 um 4:40 Uhr

  • Hallo Emilie, besteht die Möglichkeit, dass Drawables als Schaltflächenhintergrund aus irgendeinem Grund beim ersten Mal nicht angezeigt werden? Derzeit habe ich das Problem, dass ich den Bereich der Schaltfläche berühren muss, damit der Hintergrund angezeigt wird, oder ausschalten und zur Aktivität zurückkehren. (Dies passiert nur auf einem HDPI-Bildschirm, funktioniert aber gut auf meinem Mdpi). Ich glaube, dass andere dieses Problem auch haben könnten. Ist Ihr Code für alle Bildschirmdichten getestet?

    – sie verschlüsselt Dinge

    30. Oktober 2012 um 13:29 Uhr


  • Hallo, nein, das wurde vor einiger Zeit geschrieben und war damals nur für ein Gerät. Ich bin mir nicht sicher, welche Art von Problem auftreten könnte, aber soweit ich weiß, sollten mehrere Bildschirmdichten und Layouts kein Problem darstellen.

    – Emil

    2. November 2012 um 12:12 Uhr

  • Danke, ich weiß nicht genau, was ich falsch gemacht habe, aber am Ende hatte ich nur Folgendes: buttonStates = new StateListDrawable(); buttonStates.addState(neue int[]{statePressed}, ApplicationConstants.moduleImageLoader.findImageByName(drawable_pressed)); buttonStates.addState(neue int[]{-stateFocused, -statePressed, -stateSelected}, ApplicationConstants.moduleImageLoader.findImageByName(drawable_normal));

    – sie verschlüsselt Dinge

    9. November 2012 um 20:03 Uhr


  • Dies ist die erste Stelle, an der ich sehe, dass für Zustände, die auf „false“ gesetzt sind, negative Werte verwendet werden müssen. Die Dokumentation ist darüber nicht sehr eindeutig. Danke für den Tipp!

    – eocanha

    2. Oktober 2013 um 13:34 Uhr

868950cookie-checkErsetzen Sie Selektorbilder programmgesteuert

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy