Ganti gambar pemilih secara terprogram

116

Saya memiliki ImageView yang memiliki sumber gambar yang dapat digambar yang disetel ke pemilih. Bagaimana cara mengakses pemilih secara terprogram dan mengubah gambar dari status yang disorot dan tidak disorot?

Berikut adalah kode pemilih:

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

Saya ingin bisa mengganti btn_icon_hldan btn_icondengan gambar lain.

tetesOfJupiter
sumber
bukankah lebih mudah memiliki dua penyeleksi dan menukar mereka?
bigstones
2
Masalahnya adalah Anda bisa mendapatkan ratusan file xml.
Emile

Jawaban:

244

Sejauh yang dapat saya temukan (saya telah mencoba melakukan sesuatu yang serupa sendiri), tidak ada cara untuk mengubah satu keadaan setelah StateListDrawable telah ditentukan. Namun, Anda dapat menentukan yang BARU melalui kode:

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

Dan Anda bisa menyimpan dua di antaranya, atau membuat yang berbeda sesuai kebutuhan.

Kevin Coppock
sumber
1
Saya tidak dapat menambahkan ini ke tampilan gambar. setState tidak tersedia di sana.
tetesOfJupiter
2
sebenarnya saya menemukannya, setImageDrawable () Terima kasih banyak itu berhasil dan menghemat sekitar 40 file xml!
tetesOfJupiter
2
Jadi saya punya catatan terkait lainnya untuk ini. Saya berharap Anda bisa menjawab. Saya mengatur pemilih ini pada ImageView yang ada di dalam Kontrol Kustom. Kontrol kustom juga memiliki pemilih sebagai latar belakang. Jadi, pemilih dari seluruh kontrol berfungsi, sedangkan pemilih ImageView tidak. Apakah ada kesalahan yang saya lakukan? Apakah ada urutannya?
tetesOfJupiter
1
Sama-sama! Ya, saya tidak tahu mengapa saya menempatkan setState, harus setImageDrawable, Anda benar. Untuk pertanyaan Anda yang lain, saya sarankan untuk memposting pertanyaan baru dengan kode untuk kontrol khusus Anda dan pemilihnya, saya tidak yakin dengan jawabannya.
Kevin Coppock
3
saya menggunakan kode yang sama. selalu gambar yang telah saya tentukan dalam ----> status int [] {} baru tetap ada. dimana saya salah ??
KK_07k11A0585
6

Saya memiliki masalah yang sama dan melangkah lebih jauh untuk menyelesaikannya. Namun satu-satunya masalah adalah Anda tidak dapat menentukan NavStateListDrawable dalam xml, jadi Anda harus menyetel latar belakang elemen UI Anda melalui kode. Metode onStateChange kemudian harus diganti untuk memastikan bahwa setiap kali level drawable utama berubah, Anda juga memperbarui level daftar level anak.

Saat membuat NavStateListDrawable Anda harus meneruskan level ikon yang ingin Anda tampilkan.

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

Untuk semua status drawable tombol navigasi yang berbeda, saya memiliki sesuatu seperti berikut ini.

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

Saya akan memposting ini sebagai pertanyaan dan jawaban, tetapi mengingat Anda telah mengajukan pertanyaan itu sendiri, ini dia. Catatan, ini menghemat banyak definisi file xml. saya turun dari sekitar 50-100 definisi xml menjadi sekitar 4 !.

Emile
sumber
Kode navstatelistdrawable secara efektif membuat xml pemilih berlebihan.
Emile
Hai emilie, Adakah kemungkinan drawable sebagai latar belakang tombol tidak akan muncul pertama kali karena alasan apa pun. Saat ini saya mendapatkan masalah di mana saya perlu menyentuh area tombol agar latar belakang muncul, atau beralih dan beralih kembali ke aktivitas. (Ini hanya terjadi pada layar hdpi, tetapi berfungsi dengan baik pada mdpi saya). Saya yakin orang lain mungkin mengalami masalah ini juga. Apakah kode Anda diuji untuk semua kepadatan layar?
ryvianstyron
Hai, tidak, ini ditulis cukup lama dan hanya untuk satu perangkat pada saat itu. Saya tidak yakin jenis masalah apa yang mungkin timbul meskipun sejauh yang saya ketahui beberapa kepadatan layar dan tata letak seharusnya tidak menimbulkan masalah.
Emile
Terima kasih, saya tidak begitu tahu apa yang saya lakukan salah tetapi pada akhirnya saya hanya memiliki yang berikut: buttonStates = new StateListDrawable (); buttonStates.addState (int baru [] {statePressed}, ApplicationConstants.moduleImageLoader.findImageByName (drawable_pressed)); buttonStates.addState (int baru [] {- ​​stateFocused, -statePressed, -stateSelected}, ApplicationConstants.moduleImageLoader.findImageByName (drawable_normal));
ryvianstyron
1
Ini adalah tempat pertama di mana saya melihat bahwa nilai negatif harus digunakan untuk status disetel ke salah. Dokumentasinya tidak terlalu jelas tentang itu. Terima kasih atas tipnya!
eocanha