webentwicklung-frage-antwort-db.com.de

Touch-Feedback mit RecyclerView und CardView

Ich würde gerne Touch-Feedback für meine Open-Source-Bibliothek aktivieren.

Ich habe ein RecyclerView und ein CardView erstellt. Das CardView enthält verschiedene Bereiche mit unterschiedlichen onClick Aktionen. Jetzt würde ich gerne den Ripple-Effekt auslösen, wenn ein Benutzer irgendwo auf die Karte klickt, aber ich bin nicht in der Lage, dieses Verhalten zu erzielen.

Dies ist meine Liste, die Sie auch auf GitHub finden können: 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>

Und das onClick wird auf 3 Teile dieses Layouts gesetzt. libraryCreator, libraryDescription und libraryBottomContainer.

Ich hoffe, jemand hat eine Idee, was hier falsch läuft.

Danke für Ihre Hilfe.

67
mikepenz

Ich konnte das Problem jetzt lösen.

Das Problem ist, dass ich onClickListener für die TextViews verwende und dieser Klicklistener verhindert, dass der RippleForeground über das Berührungsereignis benachrichtigt wird. Die Lösung besteht also darin, einen TouchListener in diesen TextViews zu implementieren und das Touch-Ereignis zu durchlaufen.

Die Klasse ist sehr einfach und kann überall verwendet werden:

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

Es kann verwendet werden, indem man dies als TouchListener hinzufügt:

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

Dieser Listener übergibt das Touch-Ereignis lediglich an CardView und löst den richtigen Ripple-Effekt aus. (Sie können dies auch ändern, um eine Ansicht zu erhalten. Es sollte nicht auf eine CardView beschränkt sein.)

10
mikepenz

Angenommen, Sie verwenden das Material/Appcompat-Design und Lollipop, dann funktionierte dies, indem die CardView die folgenden Attribute aufweist:

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

CardLayout ist nur eine Unterklasse von ViewGroup.

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

sollte den Trick machen.

UPDATE:

(Sieht so aus, als würden Sie versuchen, eine benutzerdefinierte Ripple-Farbe zu verwenden.)

Versuchen Sie es mit einer Welligkeit, die mit einer benutzerdefinierten Farbe als Hintergrund gezeichnet werden kann (ich habe dies nicht verwendet, daher kann ich dieses Verhalten nicht überprüfen.) Siehe: Dokumentation oder Frage , um zu erhalten du hast angefangen.

52
Avinash R

für mich:

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

machte es endlich klappen. Siehe Hintergrund von recyclerView/Inhalt hinter dem Element und den Ripple-Effekt, der mit recyclerView verwendet wird.

22
cV2

Keine der obigen Antworten hat für mich funktioniert oder war zu kompliziert.

Dann wurde mir klar, dass ich in THE RECYCLERVIEW ADAPTER LAYOUT die folgenden Eigenschaften festlegen musste.

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

Dann habe ich es zum Arbeiten gebracht.

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

Wenn Sie statt des Hintergrunds den Vordergrund verwenden, müssen Sie weder klickbar noch fokussierbar verwenden

9
sativa

In meinem Fall musste ich auch benutzerdefinierten Hintergrund und Ripple-Effekt anzeigen. Ich habe dies also erreicht, indem ich diese beiden Attribute auf das Stammlayout meines Recycling-Ansichtselements angewendet habe:

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

Hatte das gleiche Problem wie Jiang:

Ich muss die Attribute auf die Layout-Datei setzen, die die RecycleView aufbläst.

Mein Hauptlayout: (Nicht hier die Eigenschaften hinzufügen!)

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

Mein RecycleViewAdapter:

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

Meine list_center_item.xml (Fügen Sie die Eigenschaften hier hinzu!)

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

Sie müssen folgende Zeilen in das Layout einfügen, das Sie unter CardView verwenden

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

Beispiel

<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

Das eigentliche dumme Problem war in meinem Fall folgendes ....

Technisch ist es nicht so, wie es hier in meinem Fall jeder vorschlägt. Das eigentliche Problem ist, dass Sie Android nicht verwenden sollten: clickable = "true" überall in LayoutView, RelativeView oder TextView.

Es sollte nur in CardView sein.Dann funktioniert es wie Charme

Android:focusable="true" Wird nicht wirklich benötigt.

Fügen Sie einfach Folgendes in Ihre CardView ein

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