Ajout d'un effet d'entraînement à RecyclerView item

105

J'essaye d'ajouter l'effet d'entraînement à l'élément de RecyclerView. J'ai jeté un coup d'œil en ligne, mais je n'ai pas trouvé ce dont j'avais besoin. Je suppose que cela doit être un effet personnalisé. J'ai essayé l'attribut android: background au RecyclerView lui-même et l'ai réglé sur "? Android: selectableItemBackground" mais cela n'a pas fonctionné .:

    <android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:clickable="true"
    android:background="?android:selectableItemBackground"
    android:id="@+id/recyclerView"
    android:layout_below="@+id/tool_bar"/>

C'est le RecyclerView auquel j'essaie d'ajouter l'effet:

entrez la description de l'image ici

Georgi Koemdzhiev
la source
1
Je rouvre ceci comme n'étant pas un double de cette question . Bien que les solutions puissent être similaires, il y a certains aspects d'un avoir CardViewdans cette question qui ne se rapportent pas à cette question plus générale.
Suragch
@Suragch Merci d'avoir remarqué la différence :)
Georgi Koemdzhiev

Réponses:

222

J'ai découvert. La seule chose que j'avais à faire est d'ajouter cet attribut:

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

à l'élément racine de la mise en page que mon adaptateur RecyclerView gonfle comme ça:

<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="wrap_content"
    android:paddingTop="8dp"
    android:paddingBottom="8dp"
    android:background="?android:attr/selectableItemBackground"
    tools:background="@drawable/bg_gradient">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="17sp"
        android:layout_marginLeft="15dp"
        android:layout_marginStart="15dp"
        android:id="@+id/shoppingListItem"
        android:hint="@string/enter_item_hint"
        android:layout_centerVertical="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"/>

    <CheckBox
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/shopping_list_item_checkbox_label"
        android:id="@+id/shoppingListCheckBox"
        android:layout_centerVertical="true"
        android:layout_marginRight="15dp"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:checked="false"/>

</RelativeLayout>

Résultat:

entrez la description de l'image ici

Si vous ne parvenez toujours pas à voir l'effet d'entraînement, ajoutez également ces lignes à l'élément racine de la mise en page.

android:clickable="true"
android:focusable="true"
Georgi Koemdzhiev
la source
3
Et si l'élément racine est CardView?
Nabin
6
@SpiderMan Vous devez écrire votre code dans une disposition relative ou linéaire, puis le placer dans la disposition de la carte.
SanVed
7
@pronoobsanved, cela m'a aidé! Pour ceux qui sont toujours confrontés au problème, CardView prend une seule mise en page en tant qu'enfant. Pour cet enfant, définissez cliquable, focusable aussi vrai et arrière-plan que? Attr / selectedItemBackground
Vamsi Challa
42
@NabinKhadka pour un CardView l'a défini comme premier plan à la place, c'estandroid:foreground="?android:attr/selectableItemBackground"
Lorne Laliberte
6
J'ai dû ajouter l'option android:clickable="true"aussi pour faire ce travail
Joaquin Iurchuk
69

Comme déjà répondu, la solution la plus simple consiste simplement à ajouter l'un des éléments suivants comme RecyclerViewarrière-plan de votre ligne:

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

Cependant, si vous rencontrez des problèmes avec cette méthode ou si vous souhaitez un contrôle plus fin sur les couleurs, vous pouvez effectuer les opérations suivantes.

Effet d'ondulation personnalisé

Cette réponse commence par cet exemple simple d'Android RecyclerView . Cela ressemblera à l'image suivante.

Exemple d'effet d'entraînement GIF

Ajouter un sélecteur pour les appareils pré-API 21

Avant l'API 21 (Android 5.0 Lollipop), le fait de cliquer sur un RecyclerViewélément modifiait simplement sa couleur d'arrière-plan (pas d'effet d'entraînement). C'est aussi ce que nous allons faire. Si vous avez toujours des utilisateurs avec ces appareils, ils sont habitués à ce comportement, nous n'allons donc pas trop nous en préoccuper. (Bien sûr, si vous voulez vraiment l'effet d'entraînement pour eux aussi, vous pouvez utiliser une bibliothèque personnalisée .)

Cliquez avec le bouton droit sur votre res/drawabledossier et choisissez Nouveau> Fichier de ressources dessinables . Appelez ça custom_ripple. Cliquez sur OK et collez le code suivant.

custom_ripple.xml

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorAccent" />
        </shape>
    </item>
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/transparent" />
        </shape>
    </item>
</selector>

J'ai utilisé colorAccentcomme couleur de surbrillance pour l'état pressé car elle était déjà disponible, mais vous pouvez définir la couleur de votre choix.

Ajouter un effet d'entraînement pour les appareils API 21+

Cliquez avec le bouton droit sur votre res/drawabledossier et choisissez Nouveau> Fichier de ressources dessinables . Appelez à custom_ripplenouveau. Ne cliquez pas sur OK, cette fois, cependant. Dans la liste des qualificatifs disponibles, choisissez Version , puis cliquez sur le bouton >> et écrivez 21pour le niveau d'API de plate - forme . Cliquez maintenant sur OK et collez le code suivant.

v21 / custom_ripple.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorAccent">

    <item
        android:id="@android:id/mask"
        android:drawable="@android:color/white" />
</ripple>

Encore une fois, j'ai utilisé colorAccentla couleur ondulée car elle était disponible, mais vous pouvez utiliser la couleur de votre choix. Le masque limite l'effet d'entraînement uniquement à la disposition des lignes. La couleur du masque n'a apparemment pas d'importance , j'ai donc juste utilisé un blanc opaque.

Définir comme arrière-plan

Dans la disposition racine de votre élément RecyclerView, définissez l'arrière-plan sur l'ondulation personnalisée que nous avons créée.

android:background="@drawable/custom_ripple"

Dans l' exemple de projet avec lequel nous avons commencé, cela ressemble à ceci:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    android:background="@drawable/custom_ripple"
    android:padding="10dp">

    <TextView
        android:id="@+id/tvAnimalName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="20sp"/>

</LinearLayout>

Fini

C'est tout. Vous devriez pouvoir exécuter votre projet maintenant. Merci à cette réponse et à cette vidéo YouTube pour obtenir de l'aide.

Suragch
la source
Si vous voulez avoir une couleur d'arrière-plan par défaut, supprimez simplement la ligne 'android: id = "@ android: id / mask', puis définissez la couleur du dessin sur ce que vous voulez.
Jordan Hochstetler
26

Je pense qu'il y a un petit détail qui manque.

Si vous n'obtenez toujours pas l'effet d'entraînement après l'ajout, android:background="?android:attr/selectableItemBackground"essayez d'ajouter ces lignes suivantes à la racine de la mise en page.

android:clickable="true"
android:focusable="true"

Ceux-ci garantiront que la vue est cliquable et activeront l'effet d'entraînement avec l' attribut d' arrière - plan mentionné ci-dessus

Sriram R
la source
5

ajoutez ces lignes dans la vue racine xml de votre adaptateur

android:background="?attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
Gundu Bandgar
la source
2

Une approche simple et personnalisée consiste à définir un thème de vue comme indiqué ici .

some_view.xml

<ImageView
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"
   android:background="?attr/selectableItemBackgroundBorderless"
   android:focusable="true"
   android:src="@drawable/up_arrow"
   android:theme="@style/SomeButtonTheme"/>

some_style.xml

<style name="SomeButtonTheme" >
   <item name="colorControlHighlight">@color/someColor</item>
</style>

D'autres implémentations personnalisées peuvent être trouvées ici .

Adam Hurwitz
la source
1

Utilisation d'un style de bouton

Cela a fonctionné pour moi d'innombrables.

Ajoutez le style de bouton sans bordure à l'élément racine de votre mise en page. Il n'y a pas besoin focusableni d' clickableattributs, le style par défaut encapsule tout cela pour vous.

<androidx.constraintlayout.widget.ConstraintLayout
    style="@android:style/Widget.Material.Button.Borderless"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
Felix Favor Chinemerem
la source
cool, mais cela ajoute du rembourrage
ededede
@ededede Vous pouvez utiliser les attributs XML min-height, max-height, width ... pour l'ajuster à votre goût.
Felix Favor Chinemerem