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.
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.)
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"
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.
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.
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.
Android:foreground="?android:attr/selectableItemBackground"
Wenn Sie statt des Hintergrunds den Vordergrund verwenden, müssen Sie weder klickbar noch fokussierbar verwenden
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"
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"
/>
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">
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>