Обратная связь с RecyclerView и CardView

Мне бы хотелось включить сенсорную обратную связь для моей библиотеки Open Source.

Я создал RecyclerView и CardView. CardView содержит разные области с различными действиями 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 части этого макета. libraryCreator, libraryDescription и libraryBottomContainer.

Я надеюсь, что кто-то понял, что здесь происходит не так.

Спасибо за вашу помощь.

Ответ 1

Теперь я смог решить проблему.

Проблема в том, что я использую onClickListener в TextViews, и этот прослушиватель кликов предотвращает уведомление RippleForeground о событии touch. Таким образом, решение состоит в том, чтобы реализовать TouchListener в этих TextViews и пройти через сенсорное событие.

Класс действительно прост и может использоваться везде:

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 и активирует правильный эффект пульсации. (Вы также можете изменить это, чтобы получить любое представление. Он не должен ограничиваться CardView)

Ответ 2

Предполагая, что вы используете тему Material/Appcompat и Lollipop, я получил это для работы, сделав CardView следующими атрибутами:

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

Ответ 3

CardLayout - это просто подкласс ViewGroup, поэтому настройка:

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

должен сделать трюк.

UPDATE:

(похоже, вы пытаетесь использовать собственный цвет пульсации.)

Попробуйте использовать рябку с настраиваемым цветом в качестве фона (я не использовал это, поэтому я не могу проверить это поведение.) см.: документация или question, чтобы начать работу.

Ответ 4

для меня:

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

сделал это, наконец, работать. см. фон recyclerView/content позади элемента, а также см. эффект пульсации, используемый с recyclerView.

Ответ 5

Ни один из вышеперечисленных ответов не работал у меня или был слишком сложным.

Тогда я понял, что должен был установить следующие свойства в LAYOUT RECYCLERVIEW ADAPTER.

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

Затем я получил его для работы.

Ответ 6

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

Если вместо фона вместо фона используется фон, вам не нужно использовать интерактивный или настраиваемый

Ответ 7

В моем случае мне нужно было показать собственный фон и эффект пульсации. Таким образом, я достиг этого, применяя эти два атрибута в корневом макете элемента моего ресайклера:

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

Ответ 8

Была та же проблема, что и Цзян:

Я должен установить атрибуты в макет файл, который накачивает RecycleView.

My Main-Layout: ( Не добавлять свойства здесь!)

<?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"
/>

Ответ 9

Вам нужно добавить следующие строки в макете, которые вы используете в 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">