Adición de efecto dominó al elemento RecyclerView

105

Estoy tratando de agregar Ripple Effect al elemento de RecyclerView. Eché un vistazo en línea, pero no pude encontrar lo que necesitaba. Supongo que tiene que ser un efecto personalizado. Probé el atributo android: background en el propio RecyclerView y lo configuré en "? Android: selectableItemBackground" pero no funcionó:

    <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"/>

Este es el RecyclerView al que estoy tratando de agregar el efecto:

ingrese la descripción de la imagen aquí

Georgi Koemdzhiev
fuente
1
Estoy reabriendo esto como no un duplicado de esta pregunta . Aunque las soluciones pueden ser similares, hay ciertos aspectos de tener un CardViewen esa pregunta que no pertenecen a esta pregunta más general.
Suragch
@Suragch Gracias por notar la diferencia :)
Georgi Koemdzhiev

Respuestas:

222

Me di cuenta de. Lo único que tuve que hacer fue agregar este atributo:

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

al elemento raíz del diseño que mi adaptador RecyclerView infla así:

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

Resultado:

ingrese la descripción de la imagen aquí

Si aún no puede ver el efecto dominó, agregue estas líneas también al elemento raíz del diseño.

android:clickable="true"
android:focusable="true"
Georgi Koemdzhiev
fuente
3
¿Qué pasa si el elemento raíz es CardView?
Nabin
6
@SpiderMan Debes escribir tu código dentro de un diseño relativo o lineal y luego colocarlo dentro del diseño de tarjeta.
SanVed
7
@pronoobsanved, ¡esto me ayudó! Para aquellos que todavía enfrentan el problema, CardView toma un diseño único cuando era niño. Para ese niño, establezca que se puede hacer clic, enfocable como verdadero y el fondo como? Attr / selectedableItemBackground
Vamsi Challa
42
@NabinKhadka para un CardView lo configuró como primer plano, es decirandroid:foreground="?android:attr/selectableItemBackground"
Lorne Laliberte
6
Tuve que agregar la opción android:clickable="true"también para que esto funcione
Joaquin Iurchuk
69

Como ya se respondió, la solución más simple es simplemente agregar uno de los siguientes como RecyclerViewfondo de su fila:

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

Sin embargo, si tiene problemas con este método o si desea un control más preciso de los colores, puede hacer lo siguiente.

Efecto dominó personalizado

Esta respuesta comienza con este simple ejemplo de Android RecyclerView . Se verá como la siguiente imagen.

GIF de ejemplo de efecto ondulado

Agregar selector para dispositivos anteriores a API 21

Antes de API 21 (Android 5.0 Lollipop), hacer clic en un RecyclerViewelemento simplemente cambiaba su color de fondo (sin efecto dominó). Eso es lo que también vamos a hacer nosotros. Si todavía tiene usuarios con esos dispositivos, están acostumbrados a ese comportamiento, por lo que no nos vamos a preocupar demasiado por ellos. (Por supuesto, si realmente desea el efecto dominó para ellos, también puede usar una biblioteca personalizada ).

Haga clic con el botón derecho en su res/drawablecarpeta y elija Nuevo> Archivo de recursos dibujable . Llámalo custom_ripple. Haga clic en Aceptar y pegue el siguiente código.

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>

Lo usé colorAccentcomo color de resaltado para el estado presionado porque ya estaba disponible, pero puede definir el color que desee.

Agregar efecto dominó para dispositivos API 21+

Haga clic con el botón derecho en su res/drawablecarpeta y elija Nuevo> Archivo de recursos dibujable . Llámalo de custom_ripplenuevo. Sin embargo, no hagas clic en Aceptar todavía esta vez. En la lista de Calificadores disponibles, elija Versión , luego haga clic en el botón >> y escriba 21para el nivel de API de plataforma . Ahora haga clic en Aceptar y pegue el siguiente código.

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>

Nuevamente, usé colorAccentel color ondulado porque estaba disponible, pero puedes usar el color que quieras. La máscara limita el efecto dominó solo al diseño de la fila. El color de la máscara aparentemente no importa, así que usé un blanco opaco.

Establecer como fondo

En el diseño raíz de su elemento RecyclerView, configure el fondo con la ondulación personalizada que creamos.

android:background="@drawable/custom_ripple"

En el proyecto de ejemplo con el que comenzamos, se ve así:

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

Terminado

Eso es. Debería poder ejecutar su proyecto ahora. Gracias a esta respuesta y a este video de YouTube de ayuda.

Suragch
fuente
Si desea tener un color de fondo predeterminado, simplemente elimine la línea 'android: id = "@ android: id / mask' y luego establezca el color del dibujable en lo que desee.
Jordan Hochstetler
26

Creo que hay un pequeño detalle que se pierde.

Si aún no obtiene el efecto dominó después de agregar, android:background="?android:attr/selectableItemBackground"intente agregar las siguientes líneas en la raíz del diseño.

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

Esto garantizará que se pueda hacer clic en la vista y habilitará el efecto dominó con el atributo de fondo mencionado anteriormente

Sriram R
fuente
5

agregue estas líneas en su vista raíz xml del adaptador

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

Un enfoque simple y personalizado es establecer un tema de vista como se describe aquí .

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>

Aquí se pueden encontrar otras implementaciones personalizadas .

Adam Hurwitz
fuente
1

Usar un estilo de botón

Esto me ha funcionado incontables veces.

Agregue el Estilo de botón sin bordes al elemento raíz de su diseño. No hay necesidad de focusableo clickableatributos, el estilo predeterminado encapsula todo lo que para usted.

<androidx.constraintlayout.widget.ConstraintLayout
    style="@android:style/Widget.Material.Button.Borderless"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">
Felix Favor Chinemerem
fuente
genial, pero esto agrega relleno
ededede
@ededede Puede usar los atributos XML min-height, max-height, width ... para ajustarlo a su gusto.
Felix Favor Chinemerem