Efecto dominó en Android Lollipop CardView

192

Estoy tratando de obtener un CardView para mostrar el efecto dominó cuando lo toco configurando el atributo android: backgound en el archivo XML de actividad como se describe aquí en la página de Desarrolladores de Android, pero no funciona. No hay animación en absoluto, pero se llama al método en onClick. También he intentado crear un archivo ripple.xml como se sugiere aquí , pero el mismo resultado.

CardView como aparece en el archivo XML de la actividad:

<android.support.v7.widget.CardView
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:layout_width="155dp"
    android:layout_height="230dp"
    android:elevation="4dp"
    android:translationZ="5dp"
    android:clickable="true"
    android:focusable="true"
    android:focusableInTouchMode="true"
    android:onClick="showNotices"
    android:background="?android:attr/selectableItemBackground"
    android:id="@+id/notices_card"
    card_view:cardCornerRadius="2dp">

</android.support.v7.widget.CardView> 

Soy relativamente nuevo en el desarrollo de Android, por lo que podría haber cometido algunos errores obvios.

AkraticCritic
fuente

Respuestas:

594

Debe agregar lo siguiente a CardView:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
Jaden Gu
fuente
8
Funciona en lollipop con efecto ondulado, pero solo da color sólido cuando se ejecuta en plataformas más antiguas. Lo suficientemente bueno para mí :)
mach
16
Una pequeña observación: ¡Noté que el atributo cliqueable no es necesario e incluso puede romper algunas cosas! Tenía un GridView lleno de CardViews clicables y el oyente no funcionaba correctamente. Eliminé la etiqueta en la que se
podía
2
@joaquin sin el clic, hace que la ondulación se origine solo desde el centro
frostymarvelous
2
?android:attr/selectableItemBackgroundrequiere API nivel 11
Pratik Butani
9
Trabajando sin android:clickable="true".
Sean
30

Agregue estos dos códigos de línea en su vista xml para obtener un efecto dominó en su cardView.

android:clickable="true"
android:foreground="?android:attr/selectableItemBackground"
Abdul Rizwan
fuente
¡Increíble! foregroundFunciona con vistas de fondo personalizadas como un encanto! ¡Agradable!
sud007
24

Logré obtener el efecto dominó en la vista de tarjeta:

<android.support.v7.widget.CardView 
    xmlns:card_view="http://schemas.android.com/apk/res-auto" 
    android:clickable="true" 
    android:foreground="@drawable/custom_bg"/>

y para el custom_bg que puede ver en el código anterior, debe definir un archivo xml para dispositivos lollipop (en el paquete drawable-v21) y pre-lollipop (en el paquete dibujable). para custom_bg en el paquete drawable-v21, el código es:

<ripple 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?android:attr/colorControlHighlight">
<item
    android:id="@android:id/mask"
    android:drawable="@android:color/white"/>
</ripple>

para custom_bg en el paquete dibujable, el código es:

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

<item android:state_pressed="true">
    <shape>
        <solid android:color="@color/colorHighlight"></solid>
    </shape>
</item>
<item>
    <shape>
        <solid android:color="@color/navigation_drawer_background"></solid>
    </shape>
</item>
</selector>

entonces, en los dispositivos pre-lollipop, tendrá un efecto de clic sólido y en los dispositivos lollipop tendrá un efecto dominó en la vista de la tarjeta.

Rahul Ahuja
fuente
1
Hola, me doy cuenta de que al aplicar el selector (u ondulación) en primer plano de CardView, bloqueará a los niños en CardView en sí mismo - stackoverflow.com/questions/33763403/… ¿ Puedo saber si encuentras el mismo problema que yo? ¿O me pierdo algo? Gracias.
Cheok Yan Cheng
@CheokYanCheng: No estoy enfrentando ningún problema como el suyo, pero diría por experiencia personal que cardView tiene algunos errores para pre-lollipop. Evite usar cardview: propiedad de elevación en pre-lollipop. Lo anterior funciona bien para mí y otros votos a favor.
Rahul Ahuja
¿Puedo saber cuál es el valor de su colorHighlight & navigation_drawer_background? Si utilizó su propio color definido sin transparencia, ¿aún puede ver los elementos secundarios de su tarjeta?
Cheok Yan Cheng
@CheokYanCheng: los valores son como, <color name = "navigation_drawer_background"> ​​# FFFFFF </color> <color name = "colorHighlight"> # FF8A65 </color>
Rahul Ahuja
No trabajo para mi caso. Yo uso su selector como primer plano. Como se esperaba, el color blanco sólido (navigation_drawer_background), que se utiliza como primer plano de vista de tarjeta, bloqueará la visibilidad de todos los niños: i.imgur.com/CleYh5B.png Así es como se ve sin aplicar el selector como primer plano: i.imgur. com / ZXk5Aoq.png
Yan Cheng
14

El efecto dominó se omitió en la biblioteca de soporte de appcompat, que es lo que está utilizando. Si desea ver la onda, use la versión Android L y pruébela en un dispositivo Android L. Por el sitio AppCompat v7:

"¿Por qué no hay ondas en pre-Lollipop? Mucho de lo que permite que RippleDrawable funcione sin problemas es el nuevo RenderThread de Android 5.0. Para optimizar el rendimiento en versiones anteriores de Android, hemos dejado RippleDrawable fuera por ahora".

Mira este enlace aquí para más información

Desarrollador Paul
fuente
Eso sería todo. ¡Gracias!
AkraticCritic
39
Pero, ¿cómo pondrías el efecto dominó en cardView para Android Lollipop?
Desarrollador de Android el
¿Entonces tengo que decidir entre la compatibilidad con versiones anteriores usando appcompat o teniendo todos los efectos nuevos, usando clases del núcleo de Android pero limitándome a API 21?
Urs Reupke
Puede hacer 2 APK's, uno para 21+ y el otro para <21. O divida el código ya que 21+ no usará supportActionbar, etc. Puede parecer un gran problema, pero creo que esa es su solución.
Mathijs Segers
1
Es por eso que escribir aplicaciones de Android L "puras" no es viable en este momento. A partir de julio de 2015, se dirigirá al 12% de la base de usuarios de Android.
Glenn Bech
10

Si la aplicación con la minSdkVersionque está trabajando es de nivel 9, puede usar:

android:foreground="?selectableItemBackground"
android:clickable="true"

En cambio, a partir del nivel 11, usa:

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"

De la documentación:

clickable : define si esta vista reacciona a los eventos de clic. Debe ser un valor booleano, "verdadero" o "falso".

primer plano : define el dibujable para dibujar sobre el contenido. Esto se puede usar como una superposición. El dibujo en primer plano participa en el relleno del contenido si la gravedad está configurada para rellenar.

Filipe Brito
fuente
El uso de android: foreground = "? Android: attr / selectableItemBackground" funcionó para la compatibilidad con AndroidX, ¡gracias!
dianakarenms
6

Para mí, agregar el foregroundaCardView no funcionaba (razón desconocida: /)

Agregar el mismo diseño secundario hizo el truco.

CÓDIGO:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:card_view="http://schemas.android.com/apk/res-auto"
    android:id="@+id/card_view"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:focusable="true"
    android:clickable="true"
    card_view:cardCornerRadius="@dimen/card_corner_radius"
    card_view:cardUseCompatPadding="true">

    <LinearLayout
        android:id="@+id/card_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:foreground="?android:attr/selectableItemBackground"
        android:padding="@dimen/card_padding">

    </LinearLayout>
</android.support.v7.widget.CardView>
Prabs
fuente
2
Esto se debe a que el niño intercepta el evento, si intentas algo como agregar relleno a la vista de la tarjeta (algo así como 20dp), y haces clic en la parte donde estaría el relleno, verás el efecto dominó incluso sin que el niño tenga el conjunto de atributos de primer plano
Cruces
1
Esto también funcionó para mí, usando los nuevos Componentes de materiales: com.google.android.material.card.MaterialCardView. Tenía un elevador stateListAnimator para la vista de tarjeta para ajustar la elevación y la ondulación aplicada al diseño de restricción interna con fondo de elemento seleccionable en primer plano sin atributo cliqueable.
Patty P
No lo recuerdo ahora, pero hay una manera de configurar las vistas secundarias para que no reaccionen al evento de clic
Someone Somewhere
3

Agregue estos dos tipos de código como un hechizo para cualquier vista como Button, Linear Layout o CardView Simplemente coloque estas dos líneas y vea la magia ...

android:foreground="?android:attr/selectableItemBackground"
android:clickable="true"
Hitesh Kushwah
fuente
2

Si hay un diseño raíz como RelativeLayout o LinearLayout que contiene todos los componentes del elemento del adaptador en CardView, debe establecer el atributo de fondo en ese diseño raíz. me gusta:

<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="122dp"
android:layout_marginBottom="6dp"
android:layout_marginLeft="6dp"
android:layout_marginRight="6dp"
card_view:cardCornerRadius="4dp">

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/touch_bg"/>
</android.support.v7.widget.CardView>
Robert Lee
fuente
2

Evento de ondulación para el Cardviewcontrol de Android :

<android.support.v7.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:foreground="?android:attr/selectableItemBackground"
    android:clickable="true"
    android:layout_marginBottom="4dp"
    android:layout_marginTop="4dp" />
chavanNil
fuente
1

No estaba contento con AppCompat, así que escribí mi propio CardView y mis ondas con backport. Aquí se ejecuta en Galaxy S con Gingerbread, por lo que definitivamente es posible.

Demo de Ripple en Galaxy S

Para más detalles verifique el código fuente .

Zielony
fuente
el enlace está roto
temirbek
1

Agregue lo siguiente a su xml:

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

Y agregue a su adaptador (si es su caso)

    override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            val attrs = intArrayOf(R.attr.selectableItemBackground)
            val typedArray = holder.itemView.context.obtainStyledAttributes(attrs)
            val selectableItemBackground = typedArray.getResourceId(0, 0)
            typedArray.recycle()

            holder.itemView.isClickable = true
            holder.itemView.isFocusable = true
            holder.itemView.foreground = holder.itemView.context.getDrawable(selectableItemBackground)
        }
    }
Mateus Melo
fuente
0

Para aquellos que buscan una solución al problema del efecto dominó que no funciona en un CardView creado mediante programación (o en mi caso, una vista personalizada que extiende CardView) que se muestra en un RecyclerView, lo siguiente funcionó para mí. Básicamente, declarar los atributos XML mencionados en las otras respuestas declarativamente en el archivo de diseño XML no parece funcionar para un CardView creado mediante programación, o uno creado a partir de un diseño personalizado (incluso si la vista raíz es CardView o se usa un elemento de fusión) tienen que establecerse mediante programación de la siguiente manera:

private class MadeUpCardViewHolder extends RecyclerView.ViewHolder {
    private MadeUpCardView cardView;

    public MadeUpCardViewHolder(View v){
        super(v);

        this.cardView = (MadeUpCardView)v;

        // Declaring in XML Layout doesn't seem to work in RecyclerViews
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            int[] attrs = new int[]{R.attr.selectableItemBackground};
            TypedArray typedArray = context.obtainStyledAttributes(attrs);
            int selectableItemBackground = typedArray.getResourceId(0, 0);
            typedArray.recycle();

            this.cardView.setForeground(context.getDrawable(selectableItemBackground));
            this.cardView.setClickable(true);
        }
    }
}

Donde MadeupCardView extends CardViewFelicitaciones a esta respuesta por la TypedArrayparte.

Breeno
fuente
0
  android:foreground="?android:attr/selectableItemBackgroundBorderless"
   android:clickable="true"
   android:focusable="true"

Solo funciona la API 21 y use esto, no use esta vista de tarjeta de fila de lista

Tarun Umath
fuente
0

Utilice Material Cardview en su lugar, extiende Cardview y proporciona múltiples funciones nuevas, incluido el efecto de clic predeterminado:

<com.google.android.material.card.MaterialCardView>

...

</com.google.android.material.card.MaterialCardView>

Dependencia

implementation 'com.google.android.material:material:1.0.0'
Ankit
fuente