通过自定义选择器ListView项目背景

时间:2010-04-01 16:44:42

标签: android listview

是否可以通过列表选择器将自定义背景应用于每个Listview项目?

默认选择器为@android:color/transparent情况指定state_focused="false",但将此更改为某个自定义可绘制不会影响未选择的项目。 Romain Guy似乎建议in this answer这是可能的。

我目前正在通过在每个视图上使用自定义背景并在选择/聚焦项目时隐藏它来实现相同的效果,以便显示选择器,但是将所有这些都定义为更加优雅一个地方。

作为参考,这是我用来试图让它工作的选择器:

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

提前感谢您的帮助!

10 个答案:

答案 0 :(得分:128)

我自己一直对此感到沮丧并最终解决了这个问题。正如Romain Guy暗示的那样,你必须使用另一个状态"android:state_selected"。使用状态drawable作为列表项的背景,并为列表的listSelector使用不同的drawable状态:

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的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 :(得分:78)

当您使用填充为背景的9-patch drawable时,dglmtn的解决方案不起作用。奇怪的事情发生了,我甚至不想谈论它,如果你有这样的问题,你就知道了。

现在,如果你想拥有一个包含不同状态的列表视图和9-patch drawables(它可以用于任何drawables和颜色,我认为)你必须做两件事:

  1. 设置列表中项目的选择器。
  2. 删除列表的默认选择器。
  3. 您应该首先设置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"
        />
    

    这应该做的事情。

答案 2 :(得分:17)

永远不要为列表视图行使用“背景颜色”......

这将阻止每个选择器操作(是我的问题!)

祝你好运!

答案 3 :(得分:5)

Android开发者博客中的文章"Why is my list black? An Android optimization"详细说明了滚动时列表背景变黑的原因。简单回答:将列表中的cacheColorHint设置为透明(#00000000)。

答案 4 :(得分: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>

答案 5 :(得分:4)

你可以写一个主题:

<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是您想要的自定义选择器 对不起,我不知道怎么写我的代码

答案 6 :(得分:4)

而不是:

android:drawable="@color/transparent" 

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

答案 7 :(得分:2)

我不确定如何通过选择器本身实现所需的效果 - 毕竟,根据定义,整个列表中都有一个选择器。

但是,您可以控制选择更改并绘制您想要的任何内容。在this sample project中,我使选择器变得透明,并在所选项目上绘制一个条。

答案 8 :(得分: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" />

无需繁琐的解决方法,所有内容都可以实现。希望这个帮助

答案 9 :(得分:-3)

FrostWire团队在这里。

所有选择器废话api都无法按预期工作。在尝试了这个线程中提供的所有解决方案之后,我们只是在膨胀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;
    }
    
  3. 如果选择器实际工作真的很好,理论上它是一个很好的和优雅的解决方案,但它似乎已经破碎了。 KISS。