带有彩色背景和涟漪效果的ListView选择器

55

在Android L开发者预览版中,标准的ListView选择器使用colorControlHighlight来实现触摸时的涟漪效果,并且在未聚焦状态下具有透明背景。

我想定义一个具有有色背景并仍然以相同的高亮颜色显示触摸涟漪效果的ListView项。现在,如果我定义以下可绘制对象:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?android:colorControlHighlight">
    <item android:drawable="@color/my_background_color"/>
</ripple>

它能够工作,但涟漪效果始于ListView项的中间,不论触摸位置在哪里。如果我在ListView之外使用相同的背景,例如 LinearLayout,那么它就像预期的那样工作(涟漪效果从触摸位置开始)。


你是否在列表项上指定了背景并将列表选择器设置为null? - alanv
你可以将列表项的背景颜色简单地设置为一个颜色,然后将列表选择器保留为默认值吗?ListView 对触摸事件有特殊处理,否则可能会阻止您获得想要的效果(不过请随时在 https://code.google.com/p/android-developer-preview/wiki/FilingIssues?tm=3 提交错误报告)。 - alanv
将列表项背景设置为纯色将无效,这将覆盖列表选择器。如问题中所述,将涟漪选择器设置为项目背景不会接收来自ListView的触摸热点。我决定遵循不设置任何列表项背景并仅将涟漪设置为listSelector的模式。唯一的缺点是我不能让某些列表项具有不同的背景并保持涟漪效果,例如突出显示未读消息。 - darnmason
你解决了这个问题吗?我现在也遇到了同样的问题... - Zsolt Boldizsar
6个回答

127

我成功地使每个列表项都有不同的颜色,并保持了涟漪效果。使用任何适配器设置列表项的背景,并将列表视图设置为在顶部显示选择器:

<ListView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:drawSelectorOnTop="true" />

这将在背景上方绘制涟漪效果。


如果不将drawSelectorOnTop设置为true,则ListView中的涟漪效果无法正确显示。对我来说,它只是用涟漪颜色填充了按钮,而没有显示实际效果。这个方法解决了问题 - 谢谢! - Matt W
4
这实际上是解决这个烦人问题的最好和最简单的答案。 - Aritra Roy
2
使用这个方法可以得到水波效果,但是当水波效果消失后,item drawable 中指定的颜色会完全覆盖整个单元格,导致其中的内容无法显示。有人知道如何解决吗? - source.rar
@source.rar 然后只需设置单个 list_view_item 的背景,然后在列表视图上不放置 android:selector。 - Sheychan
2
它什么也不做。 - Oliver Dixon
显示剩余5条评论

6
据我所知,这个bug只存在于Android 5.0,而不是5.1。这个技巧似乎是使用Drawable#setHotspot,正如Google dev在这里的提示https://twitter.com/crafty/status/561768446149410816(因为晦涩的Twitter提示是一种很棒的文档形式!)
假设您有一个类似这样的行布局
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

      <LinearLayout
            android:id="@+id/row_content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:background="?attr/selectableItemBackground">

          .... content here .....

     </LinearLayout>

</FrameLayout>

以下方法适用于我:
            row.setOnTouchListener(new View.OnTouchListener() {
                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    v.findViewById(R.id.row_content)
                        .getBackground()
                        .setHotspot(event.getX(), event.getY());

                    return(false);
                }
            });

3

样例布局中,父布局的背景采用了涟漪效果。

<RelativeLayout 
                android:id="@+id/id4"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:background="@drawable/ripple_effect"
                android:clickable="true">

                <ImageView 
                    android:id="@+id/id3"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_alignParentLeft="true"
                    android:background="@drawable/image"
                    android:layout_centerVertical="true"/>

                <LinearLayout
                    android:id="@+id/id2" 
                    android:layout_width="fill_parent"
                    android:layout_height="wrap_content"
                    android:orientation="vertical"
                    android:layout_alignParentRight="true"
                    android:layout_centerVertical="true">

                    <TextView 
                        android:id="@+id/id1"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="@string/text"/>

                </LinearLayout>
            </RelativeLayout>

Ripple_effect.xml 这里你可以使用任何你喜欢的颜色。 请确保你使用的是21版本的sdk,并且有drawable-v21和style-v21文件夹,将所有v21相关的文件放在其中。

<ripple xmlns:android="http://schemas.android.com/apk/res/android" 
                  android:color="?android:colorControlHighlight">
    <item android:id="@android:id/mask">
        <shape android:shape="oval">
            <solid android:color="?android:colorAccent" />
        </shape>
    </item>

在这里,你可以使用不同的形状,例如矩形而不是椭圆形...


3
我稍微调整了 @ArhatBaid 的答案,测试过后发现它完美地运行了:
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:colorControlHighlight">
    <item android:drawable="@color/light_grey_header_navigation_drawer"/>
</ripple>

所以,这使您可以设置背景色并仍然具有涟漪效果。
对我来说,target和minSdk都是21。


3

我发现只有当你将背景应用于列表项的根元素时,它才能正常工作。

此外,考虑使用新的RecyclerView而不是ListView。

列表项视图示例:

<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="@dimen/list_padding"
    android:layout_marginLeft="@dimen/list_padding"
    android:layout_marginRight="@dimen/list_padding"
    android:padding="@dimen/list_padding"
    android:background="@drawable/ripple_bg">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Large Text"
        android:id="@+id/tvTitle"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Small Text"
        android:id="@+id/tvSubtitle" />

</RelativeLayout>

这就是我一直在寻找的答案,我认为这是问题的根源。 - Adam
我有一个RecyclerView,其中包含一个行布局,根LinearLayout具有ImageView和TextView。我已经将android:background =“@ drawable / ripple_recycler_view_row”,android:clickable =“true”和android:drawSelectorOnTop =“true”添加到我的根LinearLayout中,但是涟漪效果显示在所选行元素的背景中。 - Shridutt Kothari

2
你可以通过嵌套布局来实现此功能。只需在现有布局周围创建一个LinearLayout作为根布局,将涟漪效果设置在根布局上,并将背景颜色设置为嵌套布局的颜色即可。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/ripple_effect"
    android:orientation="vertical">

    <RelativeLayout xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/containterContent"
        android:background="@color/yourCOLOR"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- Your content -->

    </RelativeLayout>
</LinearLayout>

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