Latar belakang item ListView melalui pemilih khusus


98

Apakah mungkin untuk menerapkan latar belakang khusus ke setiap item Listview melalui pemilih daftar?

Path menetapkan pemilih standar @android:color/transparentuntuk state_focused="false"kasus, tetapi mengubah ini untuk beberapa ditarik kustom tidak mempengaruhi item yang tidak dipilih. Romain Guy sepertinya menyarankan dalam jawaban ini bahwa ini mungkin.

Saat ini saya mencapai pengaruh yang sama dengan menggunakan latar belakang khusus pada setiap tampilan dan menyembunyikannya ketika item dipilih / difokuskan / apa pun sehingga selektornya ditampilkan, tetapi akan lebih elegan jika semua ini ditentukan di satu tempat.

Sebagai referensi, ini adalah pemilih yang saya gunakan untuk mencoba dan membuat ini berfungsi:

<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="false"
        android:drawable="@drawable/list_item_gradient" />

    <!-- Even though these two point to the same resource, have two states so the drawable will invalidate itself when coming out of pressed state. -->
    <item android:state_focused="true" android:state_enabled="false"
        android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_disabled" />
    <item android:state_focused="true" android:state_enabled="false"
        android:drawable="@drawable/list_selector_background_disabled" />

    <item android:state_focused="true" android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_transition" />
    <item android:state_focused="false" android:state_pressed="true"
        android:drawable="@drawable/list_selector_background_transition" />

    <item android:state_focused="true"
        android:drawable="@drawable/list_selector_background_focus" />

</selector>

Dan inilah cara saya menyetel pemilih:

<ListView
    android:id="@android:id/list"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:listSelector="@drawable/list_selector_background" />    

Terima kasih sebelumnya atas bantuannya!

Jawaban:


128

Saya sendiri frustrasi dengan ini dan akhirnya menyelesaikannya. Seperti yang diisyaratkan oleh Romain Guy, ada keadaan lain "android:state_selected", yang harus Anda gunakan. Gunakan drawable status untuk latar belakang item daftar Anda, dan gunakan drawable status yang berbeda untuk listSelectordaftar Anda:

list_row_layout.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight"
    android:background="@drawable/listitem_background"
    >
...
</LinearLayout>

listitem_background.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_selected="true" android:drawable="@color/android:transparent" />
    <item android:drawable="@drawable/listitem_normal" />
</selector>

layout.xml yang menyertakan ListView:

...
<ListView 
   android:layout_width="fill_parent"
   android:layout_height="wrap_content"
   android:listSelector="@drawable/listitem_selector"
   />
...

listitem_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/listitem_pressed" />
    <item android:state_focused="true" android:drawable="@drawable/listitem_selected" />
</selector>

1
Terima kasih atas tanggapan yang mendalam. Seperti yang saya sebutkan dalam pertanyaan saya, inilah yang sedang saya lakukan saat ini juga dan bekerja dengan cukup baik.
shilgapira

Sayangnya, saya masih mengalami masalah dalam menyesuaikan tampilan daftar saya. Saya memposting masalah khusus saya di sini: stackoverflow.com/questions/5426385/… ; Saya sangat menghargai masukan yang mungkin Anda miliki.
LostNomad311

Ini tidak berfungsi jika Anda menggunakan drawable 9-patch dengan padding sebagai latar belakang. Saya menemukan solusi pamungkas, saya rasa, lihat jawaban saya
Michał K

Ini berfungsi untuk pasca-ICS, tetapi untuk Gingerbread seluruh daftar diwarnai dengan drawable yang ditekan atau dipilih.
gunar

Apakah ada solusi untuk pra-ICS?
Lonli-Lokli

78

Solusi oleh dglmtn tidak berfungsi jika Anda memiliki drawable 9-patch dengan padding sebagai latar belakang. Hal-hal aneh terjadi, saya bahkan tidak ingin membicarakannya, jika Anda memiliki masalah seperti itu, Anda tahu mereka.

Sekarang, Jika Anda ingin memiliki listview dengan status berbeda dan 9-patch drawable (ini akan bekerja dengan drawable dan warna apa pun, menurut saya) Anda harus melakukan 2 hal:

  1. Setel pemilih untuk item dalam daftar.
  2. Singkirkan pemilih default untuk daftar.

Yang harus Anda lakukan adalah mengatur row_selector.xml terlebih dahulu:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_enabled="true" 
     android:state_pressed="true" android:drawable="@drawable/list_item_bg_pressed" />
    <item android:state_enabled="true"
     android:state_focused="true" android:drawable="@drawable/list_item_bg_focused" />
    <item android:state_enabled="true"
     android:state_selected="true" android:drawable="@drawable/list_item_bg_focused" />
    <item
     android:drawable="@drawable/list_item_bg_normal" />
</selector>

Jangan lupakan android:state_selected. Ini berfungsi seperti android:state_focuseduntuk daftar, tetapi diterapkan untuk item daftar.

Sekarang terapkan selektor ke item (row.xml):

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="@drawable/row_selector"
>
...
</RelativeLayout>

Buat pemilih transparan untuk daftar:

<ListView
    android:id="@+id/android:list"
    ...
    android:listSelector="@android:color/transparent"
    />

Ini harus melakukan hal itu.


1
+1, Saya tidak melihat jawaban Anda sebelumnya, saya menemukan hasil yang sama saat melakukannya sendiri. Namun terima kasih telah menyebutkan tentang 9-patch drawable, saya yakin ini bisa berguna dalam implementasi saya di masa mendatang. Ini harus menjadi jawaban terbaik karena metode ini lebih bersih dan mudah dirawat.
IsaacCisneros

28
Maaf, tapi ini adalah hal-hal yang kadang membuat berpikir mengapa apis UI sialan ini harus begitu jelek. Android masih memiliki banyak hal yang harus dilalui. Hal mendasar seperti itu seharusnya tidak menjadi PITA seperti itu.
Gubatron

2
+1 Terima kasih, terima kasih, terima kasih. Melompati semua rintangan ini untuk mencapai sesuatu yang sangat mendasar. Semua keadaan ini sangat membingungkan.
Moritz

3
Alih-alih android: listSelector = "@ drawable / list_selector" cukup tulis android: listSelector = "@ android: color / transparent". Tidak perlu list_selector.xml ekstra.
Sofi Software LLC

1
Benar, pemilih daftar yang tidak merusak hanya bisa menjadi @android: color / transparent alih-alih pemilih xml Anda sendiri. Baru mencobanya. Hal yang tidak berfungsi adalah @ null, yang mengejutkan saya karena seharusnya menyatakan: "tidak ada pemilih daftar" dan karena pemilih daftar ditarik di belakang item, tidak ada yang harus ditarik. Tapi itu tidak berhasil, pemilih default adalah saat itu ...
Zordid

17

Jangan pernah menggunakan "warna latar belakang" untuk baris tampilan daftar Anda ...

ini akan memblokir setiap tindakan pemilih (adalah masalah saya!)

semoga berhasil!


3
Ini tidak benar. Cukup gunakan pemilih sebagai latar belakang, bukan warna statis atau drawable
Michał K

ini dimaksudkan sebagai "warna latar belakang". terima sepenuhnya kata-katamu.
cV2

Saya sampai di sini karena saya membutuhkan selektor sekarang yang telah saya gunakan setBackgroundColordengan "warna". Sigh ... Gunakan setBackgroundatau setBackgroundDrawablesesuai dengan versi API Anda dengan selector.
EpicPandaForce

5

Artikel "Mengapa daftar saya hitam? Pengoptimalan Android" di Blog Pengembang Android memiliki penjelasan lengkap tentang mengapa latar belakang daftar menjadi hitam saat di-scroll. Jawaban sederhana: setel cacheColorHint pada daftar Anda menjadi transparan (# 00000000).


1
Kesederhanaan teladan tetapi bekerja dengan sangat baik. Terima kasih untuk Romain Guy ... <ListView ... android: cacheColorHint = "# 00000000"> </ListView> Semuanya!
Eric JOYÉ

Jangan berterima kasih pada Romain Guy. Dia bagian dari masalah. Seharusnya tidak ada begitu banyak "trik tersembunyi" atau peretasan lain di OS seperti ini. Meskipun saya suka Android, ini adalah tumpukan dogcrap yang mengepul jika dibandingkan dengan SDK lain (bahkan yang lebih baru / kurang dewasa!).
StackOverflowed

5

Cukup, jika Anda memasukkan list_row_layout.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:background="@drawable/listitem_background">... </LinearLayout>

listitem_selector.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@color/dark" android:state_pressed="true" />
    <item android:drawable="@color/dark" android:state_focused="true" />
    <item android:drawable="@android:color/white" />
</selector>

2
mengagumkan ... contoh paling sederhana
Shihab Uddin

1
Dan juga membuat pemilih listview transparan
Sayka

4

dari pada:

android:drawable="@color/transparent" 

menulis

android:drawable="@android:color/transparent"

4

Anda bisa menulis tema:

<pre>

    android:name=".List10" android:theme="@style/Theme"

theme.xml

<style name="Theme" parent="android:Theme">
        <item name="android:listViewStyle">@style/MyListView</item>
</style>

styles.xml

 <style name="MyListView" parent="@android:style/Widget.ListView">
<item name="android:listSelector">@drawable/my_selector</item>

my_selector adalah keinginan Anda untuk memilih custom selector. Maaf, saya tidak tahu cara menulis kode saya


Terima kasih atas bantuannya, tetapi ini tidak secara langsung membantu dalam menyetel latar belakang listitem default melalui pemilih.
shilgapira

2

Saya tidak yakin bagaimana mendapatkan efek yang Anda inginkan melalui selektor itu sendiri - lagipula, menurut definisi, ada satu pemilih untuk seluruh daftar.

Namun, Anda dapat mengontrol perubahan pilihan dan menggambar apa pun yang Anda inginkan. Dalam proyek contoh ini , saya membuat selektor transparan dan menggambar bilah pada item yang dipilih.


Memang, sangat masuk akal jika hanya ada paling banyak satu pemilih. Saya kira saya (atau) agak bingung dengan keberadaan <item android:state_focused="false" android:drawable="@android:color/transparent" />klausa di pemilih default.
shilgapira

Tandai, bermain-main (memiliki masalah yang sama dengan Gil) saya mencoba solusi Anda, itu hanya sebagian untuk track ball saja, nothingSeelected dipanggil ketika Anda menyentuh item hanya menggunakan sentuhan dan onItemClicked dipecat, jika Anda menginginkan sesuatu seperti itu, kemungkinan besar Anda harus melacak posisi yang dipilih dan ditekan di dalam ListView dan menggambar apa yang Anda butuhkan di Item itu sendiri (membuatnya menjadi Tampilan kustom) dan di dispatchDraw dari ListView.
codeScriber

@codeScriber: "nothingSeelected dipanggil saat Anda menyentuh item menggunakan sentuhan saja dan onItemClicked dipecat" - ini adalah perilaku normal, karena sentuhan tidak ada hubungannya dengan seleksi.
CommonsWare

2

Saya selalu menggunakan metode yang sama dan berhasil setiap saat, di mana saja: Saya hanya menggunakan selektor seperti ini

<item android:state_activated="true"  android:color="@color/your_selected_color" />
<item android:state_pressed="true" android:color="@color/your_pressed_color" />
<item android:color="@color/your_normal_color"></item>

dan setel pada ListView (INI SANGAT PENTING UNTUK MEMBUATNYA) atribut

android:choiceMode="singleChoice"

untuk textColor cukup letakkan di folder warna (PENTING, bukan folder drawable!) selektor seperti ini

<item android:state_activated="true"  android:color="@color/your_selected_textColor" />
<item android:state_pressed="true" android:color="@color/your_pressed_textColor" />
<item android:color="@color/your_normal_textColor"></item>

ini contoh template baris

<ImageView
    android:id="@+skinMenu/lblIcon"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:gravity="center_horizontal"
    android:src="@drawable/menu_catalog" />

<TextView
    android:id="@+skinMenu/lblTitle"
    style="@style/superlabelStyle"
    android:layout_width="wrap_content"
    android:layout_height="match_parent"
    android:layout_marginLeft="20dp"
    android:gravity="center_vertical"
    android:text="test menu testo"
    android:textColor="@color/menu_textcolor_selector"
    android:textSize="20dp"
    android:textStyle="bold" />

semuanya menunjukkan pekerjaan tanpa solusi yang membosankan. berharap bantuan ini


-3

Tim FrostWire di sini.

Semua api sampah pemilih tidak berfungsi seperti yang diharapkan. Setelah mencoba semua solusi yang disajikan di utas ini tidak berhasil, kami baru saja menyelesaikan masalah pada saat menggembungkan Item ListView.

  1. Pastikan item Anda mempertahankan statusnya, kami melakukannya sebagai variabel anggota MenuItem (boolean dipilih)

  2. Saat Anda memekarkan, tanyakan apakah item yang mendasarinya dipilih, jika demikian, cukup setel sumber daya dapat digambar yang Anda inginkan sebagai latar belakang (baik itu 9patch atau apa pun). Pastikan adaptor Anda mengetahui hal ini dan memanggil notifyDataChanged () ketika sesuatu telah dipilih.

        @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View rowView = convertView;
        if (rowView == null) {
            LayoutInflater inflater = act.getLayoutInflater();
            rowView = inflater.inflate(R.layout.slidemenu_listitem, null);
            MenuItemHolder viewHolder = new MenuItemHolder();
            viewHolder.label = (TextView) rowView.findViewById(R.id.slidemenu_item_label);
            viewHolder.icon = (ImageView) rowView.findViewById(R.id.slidemenu_item_icon);
            rowView.setTag(viewHolder);
        }
    
        MenuItemHolder holder = (MenuItemHolder) rowView.getTag();
        String s = items[position].label;
        holder.label.setText(s);
        holder.icon.setImageDrawable(items[position].icon);
    
        //Here comes the magic
        rowView.setSelected(items[position].selected);
    
        rowView.setBackgroundResource((rowView.isSelected()) ? R.drawable.slidemenu_item_background_selected : R.drawable.slidemenu_item_background);
    
        return rowView;
    }

Akan sangat bagus jika penyeleksi benar-benar berfungsi, secara teori ini adalah solusi yang bagus dan elegan, tetapi sepertinya itu rusak. CIUMAN.


Saya ingin mencoba solusi ini, bisakah Anda memberikan penjelasan lebih detail atau solusi lengkap? Terima kasih
Andrew Lam
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.