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.
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)
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"
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é.
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.
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.
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.
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"
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"
/>
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">
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>