使用RecyclerView和CardView进行触摸反馈


67

我很想为我的开源库启用触摸反馈。

我创建了RecyclerViewCardView。该CardView包含不同的区域不同的onClick动作。现在,如果用户单击卡中的任意位置,我希望触发波纹效果,但是我无法实现此行为。

这是我的列表项,您也可以在GitHub上找到它:https : //github.com/mikepenz/AboutLibraries/blob/master/library/src/main/res/layout/listitem_opensource.xml

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:clickable="true"
    android:background="@drawable/button_rect_normal"/>

<LinearLayout
    android:padding="6dp"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical">

    <LinearLayout
        android:gravity="center_vertical"
        android:paddingLeft="8dp"
        android:paddingRight="8dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/libraryName"
            android:textColor="@color/title_openSource"
            android:textSize="@dimen/textSizeLarge_openSource"
            android:textStyle="normal"
            android:layout_width="0dp"
            android:layout_weight="5"
            android:layout_height="wrap_content"
            android:ellipsize="end"
            android:maxLines="1"/>

        <TextView
            android:id="@+id/libraryCreator"
            android:textColor="@color/text_openSource"
            android:textStyle="normal"
            android:layout_width="0dp"
            android:layout_weight="2"
            android:layout_height="wrap_content"
            android:layout_marginTop="2dp"
            android:gravity="right"
            android:maxLines="2"
            android:textSize="@dimen/textSizeSmall_openSource"/>
    </LinearLayout>

    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_marginTop="4dp"
        android:background="@color/dividerLight_openSource"/>

    <TextView
        android:id="@+id/libraryDescription"
        android:textSize="@dimen/textSizeSmall_openSource"
        android:textStyle="normal"
        android:textColor="@color/text_openSource"
        android:padding="8dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:maxLines="20">
    </TextView>

    <View
        android:id="@+id/libraryBottomDivider"
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:layout_marginTop="4dp"
        android:background="@color/dividerLight_openSource"/>

    <LinearLayout
        android:id="@+id/libraryBottomContainer"
        android:gravity="center_vertical"
        android:paddingLeft="8dp"
        android:paddingTop="4dp"
        android:paddingRight="8dp"
        android:orientation="horizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <TextView
            android:id="@+id/libraryVersion"
            android:textColor="@color/text_openSource"
            android:textStyle="normal"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:gravity="left"
            android:maxLines="1"
            android:textSize="@dimen/textSizeSmall_openSource"/>

        <TextView
            android:id="@+id/libraryLicense"
            android:textColor="@color/text_openSource"
            android:textStyle="normal"
            android:layout_width="0dp"
            android:layout_weight="1"
            android:layout_height="wrap_content"
            android:gravity="right"
            android:maxLines="1"
            android:textSize="@dimen/textSizeSmall_openSource"/>
    </LinearLayout>
</LinearLayout>

并在onClick此布局的3个部分上进行设置。libraryCreatorlibraryDescriptionlibraryBottomContainer

我希望有人知道这里出了什么问题。

谢谢你的帮助。

Answers:


123

假设您使用的是Material / Appcompat主题和Lollipop,我通过使CardView具有以下属性来使其工作:

android:focusable="true"
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"

2
不,这没有用:/。仍然没有点击反馈。只是在没有onClick监听器的区域
mikepenz 2014年

7
@ Gak2,我认为您需要设置android:background而不是android:foreground。设置此设置使其对我有用。
Avinash R

使用前景对我没有任何帮助。如果您有什么建议,请进一步解释。
约瑟夫2015年

23
我猜你的问题是因为android:foreground仅适用于FrameLayouts或继承CardLayout之类的类(如CardView)。如果你尝试将其设置在一个RelativeLayout的或LinearLayout中,它不会工作
Gak2

7
正如@AvinashR所说,设置android:background是可行的。但是,可以得到更好的增强效果: android:clickable="true" android:background="?attr/selectableItemBackground" 这样,背景会在Lollipop之前的设备上使用默认的触摸选择器,并在Lollipop及以上版本上产生漂亮的波纹:-)
Suleiman19 2015年

52

CardLayout只是ViewGroup的子类,因此设置:

android:background="?android:attr/selectableItemBackground"

应该可以。

更新:

(看起来您正在尝试使用自定义波纹颜色。)

尝试使用具有自定义颜色的波纹可绘制对象作为背景(我没有使用过,因此我无法验证这种行为。)请参阅:文档或有关此问题的入门知识。


如何以编程方式设置它?
xpto 2015年


2
我通过设置android:focusable="true"和也得到了这个工作android:clickable="true"
Mattias 2015年

22

为了我:

android:background="?android:attr/selectableItemBackground"

使它最终起作用。请参阅recyclerView的背景/该项目后面的内容,还请参阅recyclerView所使用的涟漪效应。


14

上面的答案对我没有用,或者太复杂了。

然后,我意识到必须在RECYCLERVIEW ADAPTER布局中设置以下属性。

android:background="?android:attr/selectableItemBackground"
android:focusable="true"
android:clickable="true"

然后我开始工作了。


1
需要最低API级别为11
Mightian 2015年

1
@war_Hero这真的是问题吗?
Marcin Orlowski

是的,因为recyclerview的目的是要工作到版本7
Mightian '16

好的一面是,大多数较新的应用程序都支持豆形软糖及豆形软糖,因此您的答案也适用
Mightian '16

从技术上讲,并非如此。只需在您的代码段中寻找线索,我就能解决我的问题。真正的问题是,您不应该在android:clickable="true"所有地方都使用不必要的功能。它只能在CardView中。然后就可以了。
柯克,

10

我现在能够解决问题。

问题是我在TextViews上使用onClickListener,并且此点击侦听器阻止RippleForeground收到有关触摸事件的通知。因此,解决方案是在这些TextView上实现TouchListener并传递touch事件。

该类非常简单,可以在任何地方使用:

package com.mikepenz.aboutlibraries.util;

import android.support.v7.widget.CardView;
import android.view.MotionEvent;
import android.view.View;

/**
 * Created by mikepenz on 16.04.15.
 */
public class RippleForegroundListener implements View.OnTouchListener {
    CardView cardView;

    public RippleForegroundListener setCardView(CardView cardView) {
        this.cardView = cardView;
        return this;
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        // Convert to card view coordinates. Assumes the host view is
        // a direct child and the card view is not scrollable.
        float x = event.getX() + v.getLeft();
        float y = event.getY() + v.getTop();

        if (android.os.Build.VERSION.SDK_INT >= 21) {
            // Simulate motion on the card view.
            cardView.drawableHotspotChanged(x, y);
        }

        // Simulate pressed state on the card view.
        switch (event.getActionMasked()) {
            case MotionEvent.ACTION_DOWN:
                cardView.setPressed(true);
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                cardView.setPressed(false);
                break;
        }

        // Pass all events through to the host view.
        return false;
    }
}

可以通过将其添加为TouchListener来使用它:

RippleForegroundListener rippleForegroundListener = new RippleForegroundListener();
older.libraryCreator.setOnTouchListener(rippleForegroundListener);

该侦听器将仅通过touch事件传递给CardView并触发正确的波纹效果。(您也可以修改它以获取任何视图。它不应仅限于CardView)


是什么older.libraryCreator.setOnTouchListener(rippleForegroundListener);
Mohit Khaitan 2015年

1
@MohitKhaitan应该将Touch传递给RippleView的视图。还有一个更新版本,不保留上下文。github.com/mikepenz/AboutLibraries/blob/master/library/src/main/...这里使用:github.com/mikepenz/AboutLibraries/blob/...
mikepenz

我对此表示赞同,因为与其他答案不同,它正确地指出了我的LinearLayout(在我的情况下,我使用LinearLayout代替CardView)未获得选择效果的原因。但是您的解决方案似乎并不那么容易。这是Google的意图吗?仅靠布局XML文件不能做到这一点吗?
该死的蔬菜

1
我通过将TextView子类化来创建UntouchableTextView,并覆盖onTouchEvent并返回false。方法主体只是“ return false”,但是样板代码(尤其是构造函数)有点烦人。现在,我在布局XML文件中用UntouchableTextView替换了TextView,LinearLayout获得了touch事件。我希望TextView具有像android:hitTest =“ false”这样的简单属性,因此可以在一行中完成...
该死的蔬菜

现在我终于知道了问题所在,但是您的解决方案有一个问题:滑动事件也被认为是单击,并且点击效果有效
temirbek

9
android:foreground="?android:attr/selectableItemBackground"

如果您使用前景而不是背景,则无需使用可点击或可聚焦


尝试了所有其他答案,只需将其添加到CardView!中,对我来说就完美了。
Lancelot

也可以与不同颜色的卡片完美配合。谢谢!
Ridcully

5

就我而言,我还需要显示自定义背景和波纹效果。因此,我实现这一目标的方法是将这两个属性应用于我的回收站视图项目的根布局:

android:background="@drawable/custom_bg"
android:foreground="?android:attr/selectableItemBackground"

4

与江有同样的问题:

我必须将属性设置为布局文件,这会使RecycleView膨胀。

我的主布局:(不要在此处添加属性!)

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">


<android.support.v7.widget.RecyclerView
    android:id="@+id/recycler_view"
    android:scrollbars="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />

</RelativeLayout>

我的RecycleViewAdapter:

            View v = inflater.inflate(R.layout.list_center_item, parent, false);

我的list_center_item.xml(在此处添加属性!

<?xml version="1.0" encoding="utf-8"?>


<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@android:id/text1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"


android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
/>

0

您必须在下面使用的布局中添加以下行 CardView

android:clickable="true"
android:focusable="true"
android:background="@drawable/my_ripple"

<android.support.v7.widget.CardView android:layout_height="wrap_content"
android:layout_width="match_parent"
xmlns:android="http://schemas.android.com/apk/res/android">

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:background="@drawable/my_ripple">

可绘制文件的用途是@drawable/my_ripple什么?
RgSW

0

在我看来,实际的愚蠢问题如下:

从技术上讲,并非像每个人在我的案例中所建议的那样。真正的问题是,你不应该使用的Android版本:在点击=“真” uncesseriliy无处不在LayoutViewRelativeViewTextView

它只能在CardView中。 然后它就像魅力

android:focusable="true" 并不是真的需要。

只需在CardView中添加以下内容

android:clickable="true" android:foreground="?android:attr/selectableItemBackground"


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <android.support.v7.widget.CardView
        android:id="@+id/card_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="center"
        android:layout_margin="@dimen/card_margin"
        android:foreground="?android:attr/selectableItemBackground"
        android:clickable="true"
        android:elevation="3dp"
        card_view:cardCornerRadius="@dimen/card_corner_radius">

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

            <ImageView
                android:id="@+id/card_template_item_image"
                android:layout_width="match_parent"
                android:layout_height="@dimen/card_size_height"
                android:scaleType="fitXY" />

            <TextView
                android:id="@+id/card_template_item_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/card_template_item_image"
                android:paddingLeft="@dimen/card_title_padding"
                android:paddingRight="@dimen/card_title_padding"
                android:paddingTop="@dimen/card_title_padding"
                android:textSize="@dimen/card_title_size"
                android:text="@string/place_holder_item_name"/>

            <TextView
                android:id="@+id/card_template_item_sub_title"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_below="@id/card_template_item_title"
                android:paddingBottom="@dimen/card_sub_title_padding"
                android:paddingLeft="@dimen/card_sub_title_padding"
                android:paddingRight="@dimen/card_sub_title_padding"
                android:textSize="@dimen/card_sub_title_size"
                android:text="@string/place_holder_item_category"/>

        </RelativeLayout>

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

</LinearLayout>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.