ListView фон елементів за допомогою спеціального селектора


98

Чи можна застосувати спеціальний фон до кожного елемента перегляду за допомогою селектора списку?

Селектор за замовчуванням вказує @android:color/transparentна state_focused="false"випадок, але зміна цього параметра на деякий спеціальний малюнок не впливає на елементи, які не вибрані. Ромен Гай, здається, пропонує у цій відповіді, що це можливо.

В даний час я досягаю такого ж ефекту, використовуючи спеціальний фон для кожного перегляду і приховуючи його, коли елемент вибраний / сфокусований / як би там не було показано селектор, але було б більш елегантно, щоб все це було визначено в одному місці.

Для довідки, це селектор, який я використовую, щоб спробувати виконати це:

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

Ось як я встановлюю селектор:

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

Заздалегідь дякую за будь-яку допомогу!

Відповіді:


128

Я сам це засмутив і нарешті вирішив. Як натякав Ромен Гай, існує інша ситуація, "android:state_selected"яку потрібно використовувати. Використовуйте стан для малювання для фону вашого елемента списку та використовуйте інший стан для малювання 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>

layout.xml, що включає 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
Дякуємо за глибоку відповідь. Як я вже згадував у своєму запитанні, саме цим я займаюся і зараз, і це працює досить добре.
shilgapira

На жаль, у мене все ще виникають проблеми з налаштуванням перегляду списку. Я розмістив тут свої конкретні проблеми: stackoverflow.com/questions/5426385/… ; Буду вдячний за будь-який внесок у вас.
LostNomad311

Він не працює, коли ви використовуєте 9-патч-чертежі з накладкою як фон. Я знайшов остаточне рішення, я думаю, бачу свою відповідь
Michał K

Це працює для Post-ICS, але для Пряників весь список кольоровий із натиснутою або вибраною графікою для малювання.
гунар

Чи є рішення для попередньої ICS?
Lonli-Lokli

78

Рішення від dglmtn не працює, коли у вас є 9-латовий малюнок із прокладкою як фон. Дивні речі трапляються, я навіть не хочу про це говорити, якщо у вас є така проблема, ви їх знаєте.

Тепер, якщо ви хочете мати перегляд списку з різними станами та 9-латовими малюнками (я думаю, він би працював з будь-якими малюнками та кольорами, я думаю), ви повинні зробити дві речі:

  1. Встановіть селектор для елементів у списку.
  2. Позбудьтесь списку за замовчуванням для списку.

Що потрібно зробити, це спочатку встановити row_selector.xml:

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

Не забувайте android:state_selected. Це працює як android:state_focusedдля списку, але застосовано до елемента списку.

Тепер застосуйте селектор до елементів (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>

Складіть прозорий селектор для списку:

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

Це має робити.


1
+1, я не бачив вашої відповіді раніше, я натрапив на той же результат, роблячи це самостійно. Але дякую, що згадуєте про 9-кратну рисунок, я впевнений, що це може бути корисним у моїх майбутніх реалізаціях. Це має бути найкращою відповіддю, оскільки цей метод є більш чистим і ретельним.
IsaacCisneros

28
Вибачте, але це такі речі, які змушують іноді замислюватися, чому ці прокляті інтерфейси інтерфейсу повинні бути такими дурними. Android ще багато чого має пройти. Такі основні речі не повинні бути такими, як ПДФА.
Губатрон

2
+1 Дякую, дякую, дякую. Перестрибуючи всі ці обручі, щоб досягти чогось такого основного. Усі ці стани настільки дуже заплутані.
Моріц

3
Замість android: listSelector = "@ dravable / list_selector" просто напишіть android: listSelector = "@ android: color / transparent". Не потрібно додаткового list_selector.xml.
Sofi Software LLC

1
Правильно, не руйнуючий вибір списку може бути @android: color / transparent замість вашого власного селектора xml. Просто спробував. Те, що не працює, це @ null, що мене дивує, тому що в ньому повинно бути зазначено: "немає селектора списку", і оскільки селектор списку намальований за елементом, нічого не слід малювати. Але це не працює, селектор за замовчуванням повертається тоді ...
Zordid

17

Ніколи не використовуйте "колір фону" для рядків перегляду списку ...

це заблокує кожну селекторну дію (була моя проблема!)

Щасти!


3
Це не правда. Просто використовуйте селектор як фон, а не статичний колір або малюнок
Michał K

це повинно було означати "колір фону". повністю прийміть ваші слова.
cV2

Я потрапив сюди, тому що мені потрібен селектор зараз, коли я використовував setBackgroundColor"колір". Зітхніть ... Використовуйте setBackgroundабо setBackgroundDrawableвідповідно до вашої версії API за допомогою селектора.
EpicPandaForce

5

У статті "Чому мій список чорний? Оптимізація Android" в Блозі розробників Android є ґрунтовне пояснення того, чому фон списку стає чорним під час прокрутки. Проста відповідь: встановіть у своєму списку cacheColorHint прозорим (# 00000000).


1
Зразкова простота, але вона працює дуже добре. Дякуємо за Ромен Хлопець ... <ListView ... android: cacheColorHint = "# 00000000"> </ListView> Це все!
Ерік ДЖОЙ

Не дякую Ромен Гай. Він є частиною проблеми. У ОС не повинно бути так багато "прихованих трюків" чи інших хакерів. Незважаючи на те, що я люблю Android, це велика куча догмарів у порівнянні з іншими SDK (навіть новішими / менш зрілими!).
StackOverflowed

5

Досить, якщо ви введете 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
дивовижний ... найпростіший приклад
Шихаб Уддін

1
А також зробіть прозорий перемикач
списку


4

Ви можете написати тему:

<pre>

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

topic.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 - це ти хочеш користувальницького селектора. Вибачте, я не знаю, як написати свій код


Дякуємо за допомогу, але це не допомагає безпосередньо встановити фон listitem за замовчуванням за допомогою селектора.
shilgapira

2

Я не впевнений, як досягти бажаного ефекту за допомогою самого селектора - адже, за визначенням, у всьому списку є один селектор.

Однак ви можете отримати контроль над змінами вибору та намалювати все, що завгодно. У цьому зразковому проекті я роблю селектор прозорим і малюю смугу на обраному елементі.


Дійсно, має сенс мати лише один вибір. Я думаю, що мене (або було) трохи бентежить існування <item android:state_focused="false" android:drawable="@android:color/transparent" />пункту в селекторі за замовчуванням.
shilgapira

Позначте, граючи навколо (маючи ту ж проблему, що і Гіл), я спробував ваше рішення, це лише часткове лише для кульового треку, нічого не вибрано, викликається, коли ви торкаєтесь предметів лише за допомогою дотику, і onItemClicked випускається, якщо ви хочете щось подібного, швидше за все, ви повинні відслідковувати вибрані та натиснуті позиції всередині ListView та малювати те, що вам потрібно, у самому Елементі (зробіть це спеціальним переглядом) та в dispatchDraw ListView.
codeСписувач

@codeScriber: "NothingSeelected називається, коли ви торкаєтесь предметів лише за допомогою дотику, і onItemClicked запускається" - це абсолютно нормальна поведінка, оскільки дотик не має нічого спільного з вибором.
CommonsWare

2

Я завжди використовую один і той же метод, і він працює кожен раз, і де: я просто використовую такий селектор

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

і встановіть на ListView (ЦЕ ВАЖЛИВО ВАЖЛИВО ЗРОБИТИ) Атрибут

android:choiceMode="singleChoice"

для textColor просто помістіть у кольорову папку (ВАЖЛИВО, не папка, що малюється!) такий селектор

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

це зразок шаблону рядків

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

все, що показує, працює без нудних обхідних шляхів. сподіваюся, що ця допомога


-3

Команда FrostWire тут.

Всі app селектора не спрацьовують, як очікувалося. Спробувавши всі рішення, представлені в цій темі, не приносять користі, ми просто вирішили проблему в момент надуття елемента ListView.

  1. Переконайтесь, що ваш елемент зберігає його стан, ми це зробили як змінну члена MenuItem (вибрано булевий)

  2. Коли ви надуваєте, запитайте, чи вибрано базовий елемент, якщо це так, просто встановіть джерело, який ви бажаєте отримати як фон (будь то 9patch чи будь-який інший). Переконайтеся, що ваш адаптер знає про це і що він викликає notifyDataChanged (), коли щось було вибрано.

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

Було б дуже приємно, якби селектори насправді працювали, теоретично це приємне та елегантне рішення, але здається, що це зламано. KISS.


Я хочу спробувати це рішення, чи не могли б ви дати більш детальне пояснення або повне рішення? Спасибі
Ендрю Лам
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.