2011-01-15 6 views
111

Mam ImageView, który ma ustawiony zasób obrazów do selektora. Jak programowo uzyskać dostęp do selektora i zmienić obrazy podświetlonego i nie podświetlonego stanu?Programowo zastępuje obrazy selektorów.

Oto kod selektora:

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

Chcę być w stanie zastąpić btn_icon_hl i btn_icon z innymi obrazami.

+0

Czy nie byłoby łatwiej mieć dwa selektory i zamienić je? – bigstones

+2

Problem polega na tym, że możesz skończyć setkami plików xml. – Emile

Odpowiedz

238

O ile udało mi się znaleźć (próbowałem zrobić coś podobnego samemu), nie ma możliwości zmodyfikowania pojedynczego stanu po zdefiniowaniu właściwości StateListDrawable. Można jednak zdefiniować nowy za pomocą kodu:

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

A może po prostu zachować dwa z nich w kasie, lub utworzyć inny, jak jest to potrzebne.

+1

Nie mogłem dodać tego do widoku obrazu. setState nie jest dostępny na tym. – dropsOfJupiter

+2

faktycznie znalazłem to, jego setImageDrawable() Dziękuję bardzo to działało i uratowało mi około 40 plików xml! – dropsOfJupiter

+2

Mam kolejną powiązaną notatkę do tego. Miałem nadzieję, że możesz odpowiedzieć. Mam ten selektor ustawiony na ImageView, który znajduje się wewnątrz Custom Control. Kontrola niestandardowa ma również selektor jako tło. Tak więc selektor całej kontroli działa, a selektor ImageView nie. Czy jest coś, co robię źle? Czy istnieje sekwencja? – dropsOfJupiter

6

Miałem ten sam problem i poszedłem o krok dalej, aby go rozwiązać. Jedyny problem polega jednak na tym, że nie można określić NavStateListDrawable w xml, więc trzeba ustawić tło elementu interfejsu użytkownika za pomocą kodu. Następnie należy zmienić metodę onStateChange, aby zapewnić, że za każdym razem, gdy zmieni się poziom głównej szuflady, aktualizuje się również poziom listy poziomów podrzędnych.

Podczas tworzenia NavStateListDrawable musisz przejść poziom ikony, którą chcesz wyświetlić.

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

Dla wszystkich różnych stanów do rysowania przycisków nawigacyjnych mam coś takiego jak poniżej.

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

Zamierzałem opublikować to jako pytanie i odpowiedź, ale widząc, jak zadałeś właśnie to pytanie, proszę bardzo. Uwaga, to oszczędza ci wielu definicji plików XML. spadłem z około 50-100 definicji xml do około 4 !.

+0

Kod navstatelistdrawly powoduje, że selektor xml jest nadmiarowy. – Emile

+0

Witaj emilie, Czy istnieje możliwość, że elementy do rysowania jako tło przycisku nie będą wyświetlane po raz pierwszy z jakiegokolwiek powodu. Obecnie pojawia się problem polegający na tym, że muszę dotknąć obszaru przycisku, aby tło się pojawiło, lub przełączyć i wrócić do działania. (Dzieje się tak tylko na ekranie hdpi, ale działa dobrze na moim mdpi). Wierzę, że inni też mogą mieć ten problem. Czy Twój kod jest testowany pod kątem wszystkich gęstości ekranu? – ryvianstyron

+0

Cześć, nie, napisano to uczciwie z powrotem i było tylko na jedno urządzenie w tym czasie. Nie jestem pewien, jaki problem może powstać, o ile jestem świadomy wielu gęstości ekranu, a układy nie powinny stanowić problemu. – Emile