为什么ColorStateList的按下状态不能与ListView项目一起使用?

3
我正在尝试使用可变背景色的项目建立一个ListView,因此我的适配器的getView()方法会调用setBackgroundResource(),并使用适当的drawable资源设置所需的背景颜色。
如果我使用引用ColorStateList作为其颜色的ColorDrawable,则在我点击该项时,来自ColorStateList的按下状态的颜色不会被绘制。
如果我使用StateListDrawable,它引用ColorDrawable作为按下状态和不按下状态的不同ColorDrawable,当我点击该项时,我会得到期望的高亮效果。
我已经创建了一个简单的项目来演示这一点。这是ListAdapter中的getView()方法:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
    View retval = getLayoutInflater().inflate(android.R.layout.simple_list_item_1, parent, false);
    TextView textView = (TextView)retval.findViewById(android.R.id.text1);
    textView.setText("" + position);

    switch ( position ) {
        case 0:
            retval.setBackgroundResource(R.drawable.list_background_item_0);
            break;

        case 1:
            retval.setBackgroundResource(R.drawable.list_background_item_1);
            break;
    }

    return retval;
}

res/drawable/list_background_item_0.xml:

<color xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/list_background_item_0" />

res/color/list_background_item_0.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:color="@color/list_background_item_0_pressed"/>
    <item android:color="@color/list_background_item_0_default"/>
</selector>

res/drawable/list_background_item_1.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@drawable/list_background_item_1_pressed" />
    <item android:drawable="@drawable/list_background_item_1_default" />
</selector>

res/drawable/list_background_item_1_default.xml:

<color xmlns:android="http://schemas.android.com/apk/res/android" 
    android:color="@color/list_background_item_1_default" />

res/drawable/list_background_item_1_pressed.xml:

<color xmlns:android="http://schemas.android.com/apk/res/android" 
    android:color="@color/list_background_item_1_pressed" />

res/values/colors.xml:

<resources>
    <color name="list_background_item_0_default">#FFCCCC</color>
    <color name="list_background_item_0_pressed">#996666</color>
    <color name="list_background_item_1_default">#CCFFCC</color>
    <color name="list_background_item_1_pressed">#669966</color>
</resources>

列表项0使用引用了ColorStateListColorDrawable配置,并在按下时不显示高亮。列表项1则使用了StateListDrawable并在按下时显示高亮。

我更喜欢使用ColorStateList而不是StateListDrawable,因为它看起来更加简洁,每种项目类型需要少一个文件。是否有什么我错过的东西可以让我使用这种方法?如果不能按照我的期望工作,是否有人能解释一下原因呢?


非常好的问题,解释得很清楚。 - Sound Conception
我注意到对于item_0, 你的drawable文件夹中的<color> xml文件和color文件夹中的<selector> xml文件有相同的名称。既然它只是一个颜色定义,你是否尝试将第一个xml文件重命名,以便它也可以放在color文件夹中?虽然我本来不认为这样做有什么影响,但还是值得一试的。我在想这可能会让系统感到困惑,导致意外的行为。 - Sound Conception
ColorDrawable是一个非常简单的drawable,它不能管理复杂drawable的状态(例如扩展了DrawableContainerStateListDrawable)。而且,我认为第一个版本并不更加简洁,因为它将一个drawable包装在一个状态列表drawable周围,而不是使用指向正确颜色的相同单个状态列表drawable(出于某种原因,您决定将基本颜色包装在颜色xml drawable中)。 - user
@SoundConception - 感谢您的建议。我将res/color/list_background_item_0.xml重命名以避免ID过载,但没有任何改变。 - GBegen
@Luksprog - 尽管简单,ColorDrawable 可以将 ColorStateList 作为其颜色引用,并且它可以很好地选择默认颜色,但是无法选择按下的颜色。我不知道在 StateListDrawable 中引用的可绘制对象可以是颜色,感谢您的指点。这确实使得 StateListDrawable 的解决方案更加可接受。 - GBegen
1个回答

4

感谢Luksprog的评论,我学到了StateListDrawable引用的可绘制对象可以是来自colors.xml中的颜色。这使得StateListDrawable解决方案比ColorStateList版本更受欢迎。

最终方案是...

getView()方法:

  • 没有变化

res/color/list_background_item_0.xml:

  • 删除

res/drawable/list_background_item_0.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@color/list_background_item_0_pressed" />
    <item android:drawable="@color/list_background_item_0_default" />
</selector>

res/drawable/list_background_item_1.xml:

<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" android:drawable="@color/list_background_item_1_pressed" />
    <item android:drawable="@color/list_background_item_1_default" />
</selector>

res/drawable/list_background_item_1_default.xml:

  • 已删除

res/drawable/list_background_item_1_pressed.xml:

  • 已删除

res/values/colors.xml:

  • 无更改

这个解决方案比我预期的使用ColorStateList版本更加简洁。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接