Özel seçici aracılığıyla ListView öğe arka planı


98

Liste seçici aracılığıyla her Listview öğesine özel bir arka plan uygulamak mümkün müdür?

Varsayılan seçici @android:color/transparent, state_focused="false"durumu belirtir , ancak bunu bazı özel çekilebilir öğeler olarak değiştirmek, seçilmeyen öğeleri etkilemez. Romain Guy bu yanıtta bunun mümkün olduğunu öne sürüyor gibi görünüyor .

Şu anda aynı etkiyi her görünümde özel bir arka plan kullanarak ve öğe seçildiğinde / odaklandığında / her ne olursa olsun gizleyerek elde ediyorum, bu nedenle seçici gösterilir, ancak bunların hepsinin tek bir yerde tanımlanması daha zarif olur.

Referans olarak, bu çalışmayı denemek için kullandığım seçici:

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

Seçiciyi şu şekilde ayarlıyorum:

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

Herhangi bir yardım için şimdiden teşekkürler!

Yanıtlar:


128

Bu beni hayal kırıklığına uğrattı ve sonunda çözdüm. Romain Guy'ın ima ettiği gibi, "android:state_selected"kullanmanız gereken başka bir durum daha var . Liste öğenizin arka planı için çekilebilir bir durum kullanın ve listeniz için farklı bir çekilebilir durum kullanın listSelector:

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>

ListView içeren layout.xml:

...
<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
Kapsamlı yanıt için teşekkürler. Sorumda da belirttiğim gibi, şu anda tam olarak yaptığım şey bu ve gayet iyi çalışıyor.
shilgapira

Ne yazık ki, liste görünümümü özelleştirirken hala sorun yaşıyorum. Özel sorunlarımı burada yayınladım: stackoverflow.com/questions/5426385/… ; Sahip olabileceğiniz her türlü girdiden memnun olurum.
LostNomad311

Arka plan olarak dolgulu 9 yama çekmecelerini kullandığınızda çalışmaz. Nihai çözümü buldum, sanırım
cevabıma

Bu, ICS sonrası için işe yarar, ancak Gingerbread için tüm liste, basılı veya seçili çekilebilir olarak renklendirilir.
gunar

Ön ICS için herhangi bir çözüm var mı?
Lonli-Lokli

78

Dglmtn çözümü, arka plan olarak dolgulu 9 yama çekilebilir bir dosyanız olduğunda çalışmaz. Tuhaf şeyler oluyor, bunun hakkında konuşmak bile istemiyorum, eğer böyle bir sorunun varsa, onları biliyorsun.

Şimdi, farklı durumlara ve 9 yama çekmecelerine sahip bir liste görünümüne sahip olmak istiyorsanız (herhangi bir çizim ve renkle çalışacaktır, sanırım) 2 şey yapmanız gerekir:

  1. Listedeki öğeler için seçiciyi ayarlayın.
  2. Liste için varsayılan seçiciden kurtulun.

Yapmanız gereken, önce row_selector.xml'yi ayarlamaktır:

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

Unutma android:state_selected. android:state_focusedListe için olduğu gibi çalışır , ancak liste öğesi için uygulanır.

Şimdi seçiciyi öğelere uygulayın (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>

Liste için şeffaf bir seçici yapın:

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

Bu şeyi yapmalı.


1
+1, cevabınızı daha önce görmedim, kendi başıma yaparken aynı sonuca rastladım. Ancak 9 yamalı çekilebilir öğelerden bahsettiğiniz için teşekkürler, eminim ki gelecekteki uygulamalarımda faydalı olabilir. Bu en iyi cevap olmalı çünkü bu yöntem daha temiz ve bakımı yapılabilir.
IsaacCisneros

28
Üzgünüm, ama bazen bu lanet UI apilerin neden bu kadar berbat olması gerektiğini düşündüren türden şeyler bunlar. Android'in hala geçmesi gereken çok şey var. Bu tür temel şeyler böyle bir PITA olmamalıdır.
Gubatron

2
+1 Teşekkür ederim, teşekkürler, teşekkürler. Bu kadar basit bir şey elde etmek için tüm bu çemberlerden geçmek. Bütün bu durumlar çok kafa karıştırıcı.
Moritz

3
Android yerine: listSelector = "@ drawable / list_selector" sadece android: listSelector = "@ android: color / transparent" yazın. Ekstra list_selector.xml dosyasına gerek yok.
Sofi Software LLC

1
Doğru, yok etmeyen liste seçici kendi xml seçiciniz yerine yalnızca @android: color / transparent olabilir. Sadece denedim. İşe yaramayan şey @ null, beni şaşırtıyor çünkü bu, "liste seçici yok" şeklinde olmalı ve liste seçici öğenin arkasına çekildiği için hiçbir şey çizilmemelidir. Ama bu işe yaramıyor, varsayılan seçici geri döndü ...
Zordid

17

Liste görünümü satırlarınız için asla "arka plan rengi" kullanmayın ...

bu, her seçici eylemini engelleyecek (benim sorunumdu!)

iyi şanslar!


3
Bu doğru değil. Statik bir renk veya çizilebilir değil, arka plan olarak bir seçiciyi kullanın
Michał K

bunun "arka plan rengi" ile kastedilmesi amaçlanmıştır. sözlerini tamamen kabul et.
cV2

Buraya geldim çünkü artık setBackgroundColorbir "renk" ile kullandığım için bir seçiciye ihtiyacım var . İç çek ... Bir seçici ile API sürümünüze göre setBackgroundveya kullanın setBackgroundDrawable.
EpicPandaForce

5

Android Geliştiricileri Blogu'ndaki "Listem neden siyah? Bir Android optimizasyonu" başlıklı makalede , kaydırma sırasında liste arka planının neden siyaha döndüğüne dair kapsamlı bir açıklama var. Basit cevap: listenizdeki cacheColorHint'i şeffaf olarak ayarlayın (# 00000000).


1
Örnek bir basitlik ama çok iyi çalışıyor. Romain Guy için teşekkürler ... <ListView ... android: cacheColorHint = "# 00000000"> </ListView> Hepsi bu!
Eric JOYÉ

Romain Guy'a teşekkür etme. Sorunun bir parçası. Bunun gibi bir işletim sisteminde çok fazla "gizli numara" veya başka hack olmamalıdır. Android'i sevmeme rağmen, diğer SDK'larla karşılaştırıldığında (daha yeni / daha az olgun olanlar!) Büyük bir köpek kapanı yığını.
StackOverflow

5

Eğer koyarsanız yeterli 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
harika ... en basit örnek
Shihab Uddin

1
Ayrıca liste görünümü seçiciyi şeffaf hale getirin
Sayka

4

onun yerine:

android:drawable="@color/transparent" 

yazmak

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

4

Bir tema yazabilirsiniz:

<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 sizin özel seçici isteğinizdir Üzgünüm kodumu nasıl yazacağımı bilmiyorum


Yardım için teşekkürler, ancak bu, seçici aracılığıyla varsayılan liste öğesi arka planının ayarlanmasına doğrudan yardımcı olmuyor.
shilgapira

2

Seçicinin kendisi aracılığıyla istediğiniz etkiyi nasıl elde edeceğimi bilmiyorum - sonuçta, tanım gereği, tüm liste için tek bir seçici var.

Bununla birlikte, seçim değişiklikleri üzerinde kontrol sahibi olabilir ve istediğinizi çizebilirsiniz. Gelen bu örnek projede , ben seçici saydam hale ve seçilen öğe üzerinde bir bar çizin.


Aslında, yalnızca en fazla bir seçicinin olması tamamen mantıklıdır. Sanırım <item android:state_focused="false" android:drawable="@android:color/transparent" />varsayılan seçicide cümlenin varlığıyla biraz kafam karıştı (veya oldu) .
shilgapira

Mark, etrafta oynuyorum (Gil ile aynı problemi yaşıyorum) Çözümünüzü denedim, sadece pist topu için kısmi, hiçbir şey sadece dokunma ile öğelere dokunduğunuzda hissettiği çağrılıyor ve onItemClicked ateşleniyor, bu tür bir şey istiyorsanız, büyük olasılıkla ListView içindeki seçili ve basılan konumları takip etmeniz ve ihtiyacınız olanı Öğenin kendisinde (onu özel Görünüm yapın) ve ListView'in dispatchDraw'da çizmeniz gerekir.
codeScriber

@codeScriber: "Öğelere yalnızca dokunma kullanarak dokunduğunuzda ve onItemClicked tetiklendiğinde noneSeelected çağrılır" - bu tamamen normal bir davranıştır, çünkü dokunmanın seçimle hiçbir ilgisi yoktur.
CommonsWare

2

Her zaman aynı yöntemi kullanıyorum ve her zaman, her yerde işe yarıyor: Sadece bunun gibi bir seçici kullanıyorum

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

ve ListView'de (BU ÇALIŞMA YAPMAK İÇİN ÇOK ÖNEMLİDİR) özniteliği ayarlayın

android:choiceMode="singleChoice"

textColor için renk klasörüne (ÖNEMLİ, çekilebilir klasör değil!) bunun gibi bir seçici koyun

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

bu örnek bir satır şablonu

<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" />

her şey sıkıcı geçici çözümler olmadan çalıştığını gösteriyor. umarım bu yardım eder


-3

FrostWire Ekibi burada.

Tüm seçici saçmalık api beklendiği gibi çalışmıyor. Bu iş parçacığında sunulan tüm çözümleri boşuna denedikten sonra, sadece ListView Öğesini şişirme anında sorunu çözdük.

  1. Öğenizin durumunu koruduğundan emin olun, bunu MenuItem'in bir üye değişkeni olarak yaptık (boolean seçildi)

  2. Şişirdiğinizde, alttaki öğenin seçilip seçilmediğini sorun, öyleyse, arka plan olarak istediğiniz çekilebilir kaynağı ayarlayın (bir 9patch veya her neyse). Bağdaştırıcınızın bunun farkında olduğundan ve bir şey seçildiğinde notifyDataChanged () öğesini çağırdığından emin olun.

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

Seçiciler gerçekten işe yarasaydı gerçekten güzel olurdu, teoride güzel ve zarif bir çözüm, ama kırılmış gibi görünüyor. ÖPÜCÜK.


Bu çözümü denemek istiyorum, lütfen daha ayrıntılı bir açıklama veya eksiksiz bir çözüm verebilir misiniz? Teşekkürler
Andrew Lam
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.