web-dev-qa-db-fra.com

Retour tactile avec RecyclerView et CardView

J'aimerais activer les retours tactiles pour ma bibliothèque Open-Source.

J'ai créé un RecyclerView et un CardView. Le CardView contient différentes zones avec différentes actions onClick. Maintenant, j'aimerais bien déclencher l'effet Ripple si un utilisateur clique n'importe où sur la carte, mais je ne parviens pas à obtenir ce comportement.

Ceci est mon listitem, vous pouvez le trouver sur GitHub aussi: 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>

Et le onClick est défini sur 3 parties de cette mise en page. libraryCreator, libraryDescription et libraryBottomContainer.

J'espère que quelqu'un a une idée de ce qui ne va pas ici.

Merci de votre aide.

67
mikepenz

Je pouvais maintenant résoudre le problème.

Le problème est que j'utilise onClickListener sur TextViews et que cet écouteur de clic empêche le RippleForeground d'être averti de l'événement touch. La solution consiste donc à implémenter un TouchListener sur ces TextViews et à transmettre l'événement touch.

Le cours est très simple et peut être utilisé partout:

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

Il peut être utilisé en ajoutant ceci comme TouchListener:

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

Cet écouteur transmettra simplement l'événement tactile à CardView et déclenchera l'effet Ripple correct. (Vous pouvez également modifier cela pour ne prendre aucune vue. Cela ne devrait pas être limité à un CardView)

10
mikepenz

En supposant que vous utilisiez le thème Material/Appcompat et Lollipop, je dois faire en sorte que CardView possède les attributs suivants:

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

CardLayout est juste une sous-classe de ViewGroup, donc vous définissez:

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

devrait faire l'affaire.

UPDATE:

(on dirait que vous essayez d'utiliser une couleur d'ondulation personnalisée.)

Essayez d’utiliser une ondulation avec une couleur personnalisée comme arrière-plan (je n’ai pas utilisé cela, je ne peux donc pas vérifier ce comportement.) Voir: documentation ou ceci question pour obtenir vous avez commencé.

52
Avinash R

pour moi:

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

fait finalement fonctionner. voir l'arrière-plan de recyclerView/contenu derrière l'élément, ainsi que l'effet d'entraînement utilisé avec recyclerView.

22
cV2

Aucune des réponses ci-dessus n'a fonctionné pour moi ou était trop compliqué.

Ensuite, j'ai réalisé que je devais définir les propriétés suivantes dans LA DISPOSITION DE L'ADAPTATEUR RECYCLERVIEW.

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

Puis je l'ai fait au travail.

14
Jjang
Android:foreground="?android:attr/selectableItemBackground"

Si vous utilisez le premier plan à la place de l’arrière-plan, vous n’avez pas besoin d’utiliser de clic ou de mise au point.

9
sativa

Dans mon cas, j’avais besoin de montrer un effet d’arrière-plan et d’effet personnalisé. Pour y parvenir, j'ai appliqué ces deux attributs à la structure racine de mon élément recycler-view:

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

A eu le même problème que Jiang:

Je dois définir les attributs dans le fichier de présentation, qui gonfle le RecycleView.

Ma disposition principale: (ne pas ajouter les propriétés ici!)

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

Mon RecycleViewAdapter:

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

Mon list_center_item.xml (Ajoutez les propriétés ici!)

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

Vous devez ajouter les lignes suivantes dans la mise en page que vous utilisez sous CardView

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

Exemple

<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">
0
priyankvex

La question stupide était dans mon cas est la suivante ....

Techniquement, ce n'est pas le cas, comme tout le monde le suggère ici dans mon cas. Le vrai problème est que vous ne devriez pas utiliser Android: clickable = "true" partout dans le LayoutView, RelativeView ou TextView.

Cela ne devrait être que dans CardView.Alors ça marche comme un charme

Android:focusable="true" N'est pas vraiment requis.

Ajoutez simplement ce qui suit dans votre 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>
0
Kirk