【问题标题】:Android ListView State List not showing default item backgroundAndroid ListView 状态列表不显示默认项目背景
【发布时间】:2011-01-19 00:50:34
【问题描述】:

已在 SO 上阅读了许多相关问题,并查看了 Android 文档和源代码以试图弄清楚这一点,但我很难过,尽管考虑到 listSelector 似乎只对选定项目应用样式,我一点都不震惊……

我在 main.xml 中定义了一个 Listview:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <ListView  
    android:id="@android:id/list"
    android:layout_width="fill_parent" 
    android:layout_height="fill_parent"
    android:fadingEdgeLength="5dp"
    android:divider="#000000"
        android:dividerHeight="1dp"
        android:listSelector="@drawable/list_selector" />
    <TextView 
    android:id="@android:id/empty"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:gravity="center"
        android:singleLine="false"
        android:text="@string/message_list_empty" />
</FrameLayout>

引用的 listSelector 在这里(主要从 SDK 中的默认 Android 状态列表中借用:/android/platforms/android-8/data/res/drawable/list_selector_background.xml):

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <!-- the window has lost focus, disable the items -->
    <item 
        android:state_window_focused="false"
        android:drawable="@drawable/shape_row_disabled" />

    <!-- the list items are disabled -->
    <item 
        android:state_enabled="false"
        android:state_focused="true" 
        android:state_pressed="true"
        android:drawable="@drawable/shape_row_disabled" />
    <item 
        android:state_enabled="false"
        android:state_focused="true" 
        android:drawable="@drawable/shape_row_disabled" />
    <item 
        android:state_enabled="false"
        android:drawable="@drawable/shape_row_disabled" />

    <!-- the list items are enabled and being pressed -->
    <item 
        android:state_focused="true" 
        android:state_pressed="true"
        android:drawable="@drawable/shape_row_transition" />
    <item 
        android:state_focused="false" 
        android:state_pressed="true"
        android:drawable="@drawable/shape_row_transition" />

    <!-- the list items are enabled and being used -->
    <item
        android:state_focused="true"
        android:drawable="@drawable/shape_row_selected" />

    <!-- the default item -->
    <item 
        android:drawable="@drawable/shape_row" />
</selector>

引用的drawables是形状,圆角矩形,像这样:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
android:shape="rectangle">
    <gradient 
        android:startColor="#EF6100"
        android:centerColor="#FF8E00" 
        android:endColor="#EF6100" 
        android:angle="270" /> 
    <corners 
        android:bottomRightRadius="7dp" 
        android:bottomLeftRadius="7dp"
        android:topLeftRadius="7dp" 
        android:topRightRadius="7dp" /> 
</shape>

因此,最终结果应该是一个 ListView,其中项目默认具有 @drawable/shape_row 背景,然后根据状态使用不同颜色的背景。当我启动我的列表时,在状态处于活动状态时一切正常,例如项目获得焦点、被按下等,但是当没有选择项目时(即默认视图状态),项目本身具有透明背景。我曾希望州列表的最后一条规则,

<item android:drawable="@drawable/shape_row" />

会捕获该状态,但由于某种原因它无法正常工作。我已经移动了一些东西并尝试了不同的设置,但什么也没有。如果我编辑用于在 ListView 中定义列表项的 row.xml 文件并尝试添加指向 @drawable/shape_row 的特定 android:background,则每一行都会获得正确的背景,但在按下时,在焦点上, etc 状态无法处理(或者至少不能被视为背景永远不会改变)。

任何人都可以在这里指出正确的方向吗?我已经快要把这个放在床上了,但是在尝试了几乎所有事情之后,就是无法让 ListView 项目采用默认背景并通过 android:listSelector 响应已实现的状态列表。

谢谢,

保罗

编辑:

也刚刚尝试将 android:itemBackground="@drawable/shape_row" 添加到 main.xml 中的 ListView,不出所料没有运气(文档声明它应该用于指定菜单项的背景,但认为值得一试用列表项拍摄)。

尝试了另一件事,将 android:visible="true" 添加到每个选择器和项目定义中。 StateListDrawable 文档似乎表明"Provides initial visibility state of the drawable; the default value is false",但添加它并没有改变。

EDIT2:因此,根据 Qberticus 在下面所做的研究,似乎每个视图只能有一组列表选择器,这证实了列表选择器的行为。我还可以确认设置 android:drawSelectorOnTop 确实会在所选项目的前面移动选择器,但这当然会掩盖项目本身,因此我只能看到选择器本身(在我的情况下是彩色形状)。

这是设置了背景的列表的样子:

由于设置了背景,选择项目时外观没有变化。如果我将 android:drawSelectorOnTop 指令更改为 true 并选择一个项目,我会得到:

最后,如果我没有为列表项设置背景图像,则选择器会按预期工作,但是当然,没有背景图像,因为似乎没有遵循 StateSelector 的最后一条规则(不应该充当包罗万象?)对于未选择的项目,这意味着没有漂亮的自定义圆形:

所以,我的问题仍然存在;如果我没有为每个列表项设置背景,我可以看到选择器正常工作,但未选择时项目没有背景。如果我为项目设置背景,它们在未选中时看起来很棒,但背景会遮挡选择器。是不是不可能有一个带有工作选择器的独特形状的列表项?

感谢其他可以参与的人。

【问题讨论】:

    标签: android listview background state


    【解决方案1】:

    想通了,问题是当我通过android:listSelector="@drawable/list_selector" 将 ListView 的 listSelector 正确设置为状态列表时,我还需要通过android:background="@drawable/list_background" 将列表项的背景设置为另一个状态列表

    在list_background.xml状态列表中,我有:

    <?xml version="1.0" encoding="utf-8"?>
    <selector xmlns:android="http://schemas.android.com/apk/res/android"
    android:visible="true">
    
        <!-- the list items are disabled -->
    <item 
            android:state_window_focused="false"
            android:drawable="@drawable/shape_row_disabled" />
    
        <!-- the list items are enabled, in focus but not being touched/pressed (idle) -->
        <item 
            android:state_window_focused="true"
            android:state_pressed="false"
            android:state_focused="false"
            android:state_selected="false"
            android:drawable="@drawable/shape_row" />
    
        <!-- the catch-all -->
        <item 
            android:drawable="@android:color/transparent" />
    </selector>
    

    在这里找到答案:

    Changing background color of ListView items on Android

    结合我上面的列表选择器,它可以完美地工作。

    【讨论】:

    • 不幸的是,我在自定义列表视图时仍然遇到问题。我在这里发布了我的具体问题:stackoverflow.com/questions/5426385/…;如果您有任何意见,我将不胜感激。
    • 另外,将列表属性“cacheColorHint”设置为您的背景颜色。否则,在您的列表中快速滑动可能会导致出现黑色项目列表。
    【解决方案2】:

    listSelector 仅用于指定View,该View 将被绘制在与选定View 相同的位置。即,每个ListView 只有一个listSelector 实例。您可以使用drawSelectorOnTop 指定它是否可以在顶部绘制。

    如果您希望所有Views 使用状态列表,那么您应该指定子Views 的定义位置。

    我使用AbsListView 的源代码作为参考。具体AbsListView#setSelector(Drawable)AbsListView#positionSelectorAbsListView#drawSelectorAbsListView#dispatchDraw

    AbsListView#drawSelector:

    private void drawSelector(Canvas canvas) {
            if (shouldShowSelector() && mSelectorRect != null && !mSelectorRect.isEmpty()) {
                final Drawable selector = mSelector;
                selector.setBounds(mSelectorRect);
                selector.draw(canvas);
            }
    }
    

    AbsListView#positionSelector:

    void positionSelector(View sel) {
        final Rect selectorRect = mSelectorRect;
        selectorRect.set(sel.getLeft(), sel.getTop(), sel.getRight(), sel.getBottom());
        positionSelector(selectorRect.left, selectorRect.top, selectorRect.right,
                selectorRect.bottom);
    
        final boolean isChildViewEnabled = mIsChildViewEnabled;
        if (sel.isEnabled() != isChildViewEnabled) {
            mIsChildViewEnabled = !isChildViewEnabled;
            refreshDrawableState();
        }
    }
    

    来源表明只有一个mSelector 创建/使用,并且它与所选 项位于相同的边界矩形中。

    【讨论】:

    • 感谢您的辛勤工作!当您提到每个 ListView 只使用一次 listSelector 时,这就是我在 ListView XML 中指定它的目的。将每个单独的列表项(它们是 TextViews)设置为具有背景意味着 listSelector 被隐藏......没有背景意味着每个 TextView 的透明背景,直到选择器启动。我尝试使用 ListView 的 drawSelectorOnTop 指令,它工作的原因是我可以在背景上看到选择器,但它也在前景上,也掩盖了 TextView 的内容。
    • 也许不可能有一个自定义的(在我的情况下是四舍五入的)ListView 项目和正确的选择器行为......也许我需要为整个 ListView 指定一个背景,比如一种颜色,以及然后选择器将正确显示。希望有四舍五入的 ListView 项目和选择器交互,但也许这是不可能的。
    【解决方案3】:

    您可以为根布局分配默认背景,为子布局分配 selector_background,在这种情况下,如果未选择项目,则默认背景不会遮挡选择器。它对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多