使用RecyclerView和CardView触摸反馈

时间:2014-11-16 19:31:31

标签: android android-recyclerview android-cardview rippledrawable touch-feedback

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

我创建了RecyclerViewCardViewCardView包含具有不同onClick操作的不同区域。现在,如果用户点击卡中的任何位置,我很乐意触发Ripple效果,但我无法实现此行为。

这是我的礼物项目, 您也可以在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

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

感谢您的帮助。

9 个答案:

答案 0 :(得分:120)

假设您正在使用Material / Appcompat主题和Lollipop,我通过使CardView具有以下属性来实现此目的:

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

答案 1 :(得分:52)

CardLayout只是ViewGroup的子类,所以设置:

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

应该这样做。

<强>更新

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

尝试使用自定义颜色的波纹绘制作为背景(我没有使用过,所以我无法验证此行为。)请参阅:documentation或此question以帮助您入门。

答案 2 :(得分:22)

对我来说:

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

让它终于奏效了。 查看物品背后的recyclerView / content背景,还可以看到recyclelerView使用的涟漪效应。

答案 3 :(得分:10)

我现在能够解决这个问题。

问题是我在TextViews上使用onClickListener并且此单击侦听器阻止RippleForeground被通知有关触摸事件。所以解决方案是在那些TextView上实现TouchListener并通过触摸事件。

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

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);

此侦听器只会将触摸事件传递给CardView并触发正确的Ripple效果。 (您也可以修改此视图以获取任何视图。它不应仅限于CardView)

答案 4 :(得分:9)

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

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

答案 5 :(得分:5)

在我的情况下,我需要显示自定义背景和涟漪效果。所以我实现这一点的方法是在我的recycler-view项的根布局上应用这两个属性:

function (...) 
{
    if (nargs() == 0) {
    invisible(rtvs:::send_notification("!Library"))
}
else {
    base::library(...)
    }
}
<environment: namespace:rtvs>

答案 6 :(得分: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"
/>

答案 7 :(得分: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">

答案 8 :(得分:0)

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

从技术上讲,并非像每个人在我的案例中所建议的那样。真正的问题是,您不应该在LayoutViewRelativeViewTextView的任何地方都不要使用android:clickable =“ true”来代替。

它只能在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>