RecyclerView + CardView + 触摸反馈

24

有没有人解决了在 RecyclerView 内的 CardView 没有触摸反馈的谜团?

我有一个带有许多 CardViews 的 RecyclerView(一个 CardList)。当我点击任何 CardView 时,我会启动另一个 Activity。这很好用,但是我无法看到任何触摸反馈。

及时地,我已经使用以下内容配置了我的 CardView(XML):

android:clickable="true"
android:background="?android:selectableItemBackground"

谢谢!


这个回答解决了你的问题吗?[Android-L CardView 视觉触摸反馈] (https://dev59.com/I2Af5IYBdhLWcg3wmzpL) - childno͡.de
5个回答

41

背景:

CardView 会忽略 android:background,而选择只能是颜色的 app:cardBackground。边框和阴影实际上是背景的一部分,因此您无法设置自定义的背景。

解决方案:

使 CardView 内部的布局可点击,而不是卡片本身。您已经编写了这个布局所需的两个属性:

android:clickable="true"
android:background="?android:selectableItemBackground"

1
嘿!抱歉!你是对的。欺骗我的是我正在使用Theme.Material主题,它是一个“暗色”主题。自从我改用Theme.Material.Light,并使用了你的答案后,触摸反馈就发生了。 - Rafael Nascimento
这在Lollipop及以上版本中运行良好。在Kit Kat上,内部视图的背景未覆盖整个cardView(在这里您意识到Kit Kat中的阴影是假的)。它还可以,但不完美。我现在可以接受它。 - Sotti
是的,我想我遇到了同样的问题。我不记得我是如何解决它的,但是将卡片上的contentPadding设置为与负的cardCornerRadius相同的值(确切地说是其根值)应该能完成一半的工作(请确保将useCompatPadding设置为true)。第二部分是创建一个具有相同角落大小的自定义背景<shape> STATEFUL!可绘制对象。第三部分是定义一个使用涟漪效果的drawable-v21。稍后我会尝试更新答案并提供一个示例。 - Eugen Pechanec
6
对于我来说,android:foreground="?android:selectableItemBackground"CardView 上是更干净的解决方案,因为使 CardView 内部的布局可点击会禁用我的项点击侦听器。 - Carlo Espino

8

解决方案1

正如@Eugen所建议的那样,您可以使CardView内部布局可点击,这样您就可以使用android:background属性:

<android.support.v7.widget.CardView
    ...
    android:clickable="true"
    android:background="?attr/selectableItemBackground">

解决方案2

如果您不想通过使CardView内部的布局可点击来失去项目点击监听器,则可以使用android:foreground

<android.support.v7.widget.CardView
    ...
    android:clickable="true"
    android:foreground="?attr/selectableItemBackground">
额外提示:如果您不想要矩形掩码,可以使用"?attr/selectableItemBackgroundBorderless"代替"?attr/selectableItemBackground"

CardView的前景是我唯一有效的解决方案。谢谢。 - Mohamed Nageh
这段代码示例很令人困惑 - CardView 中没有布局。如果已经被卡片形状剪裁,无边框选择器的意义是什么?它看起来一样。 - Eugen Pechanec

1
创建选择器 "drawable/card_foreground_selector"。
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="#18000000"/>
            <corners android:radius="@dimen/card_radius" />
        </shape>
    </item>
    <item android:state_focused="true" android:state_enabled="true">
        <shape android:shape="rectangle">
            <solid android:color="#0f000000"/>
            <corners android:radius="@dimen/card_radius" />
        </shape>
    </item>
</selector>

并创建"drawable/card_foreground.xml"文件(您需要根据卡片的高度调整插图值

<inset xmlns:android="http://schemas.android.com/apk/res/android" android:drawable="@drawable/card_foreground_selector"
android:insetLeft="2dp"
android:insetRight="2dp"
android:insetTop="3dp"
android:insetBottom="3dp"/>

修改你的项目(item.xml)

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:contentPadding="8dp"
    android:foreground="@drawable/card_foreground">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

    // ..

    </LinearLayout>
</android.support.v7.widget.CardView>

你可以在这里查看原始帖子。

2
我没有创建新的可绘制对象,而是使用了 android:foreground="?android:selectableItemBackground" - Carlo Espino
@CarloRodríguez,这是针对AppCompat的"?selectableItemBackground"。它适用于所有平台吗?在Lollipop之前,使用自定义的drawable,因为"?selectableItemBackground"上的角没有被剪裁。 - Eugen Pechanec
@EugenPechanec 你说得对,我没有意识到在Lollipop之前角落没有被剪裁,如果卡片视图没有圆角,这仍然可能是一个不错的选择。 - Carlo Espino

1
添加 foreground 属性:
android:foreground="?android:attr/selectableItemBackground"

1
两种方法应该以相同的方式工作。 1) 如果您希望卡片视图对触摸反馈做出响应,则在卡片视图中使用此方法。
 android:foreground="?android:attr/selectableItemBackground"
        android:clickable="true"
        android:focusable="true"

如果以上方法不起作用,您可以在cardview视图组(线性/相对等)上设置此属性。
   android:background="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:focusable="true"

但是ViewHolder的itemView将无法响应触摸事件,因为它已经被子视图消耗了,所以你必须在子视图上设置点击监听器,以便在recyclerview适配器中进一步使用监听器,这样我们就可以在适配器中启用行项目的触摸和点击事件。 如果您在使用具有涟漪效果的cardview上遇到触摸和点击视图的困难,则此方法可能会有所帮助。 触摸反馈问题 第二种方法是使用传统方法使用自定义触摸选择器可绘制并设置为背景。
    <?xml version="1.0" encoding="utf-8"?>
<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="your ripple color">
    <item>
    <selector>
        <item android:state_selected="true">
            <color android:color="your selected color" />
        </item>
        <item android:state_activated="true">
            <color android:color="your selected color" />
        </item>
        <item>
            <color android:color="your normal color" />
        </item>
    </selector>
    </item>
</ripple>

文档 涟漪可绘制对象


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