Efecto ripple

ripple sample

La documentación oficial de Material Design nos transmite la importancia que tiene dotar de una correcta interacción de usuario a nuestras apps.

El concepto de interacción es muy amplio, por lo que en este apartado nos centraremos en uno de los efectos más socorridos. El Ripple.

Cuando trabajamos con materiales pulsables es importante ofrecer al usuario el feedback visual necesario, ya que gracias a él será capaz de deducir que la acción ha ocurrido adecuadamente.

¿Cómo se añade?

I. Añade la última versión de la librería de appcompat en tu archivo build.gradle.

dependencies {  
    compile 'com.android.support:appcompat-v7:X.X.X'
}

II. Añade un componente configurado con el atributo android:background o android:foreground configurado con el valor ?selectableItemBackground.

<Button  
    android:layout_width="250dp"
    android:layout_height="70dp"
    android:text="Ripple"
    android:foreground="?selectableItemBackground"
    android:background="@android:color/white"
    />

NOTA: El mismo selector puede ser aplicado al atributo android:foreground también perteneciente a todas las vistas. A veces es necesario, ya que el comportamiento de la vista sobre la que trabajas es algo especial, como ocurre con las CardView.

Ripple Borderless

Añade un componente en tu layout con el atributo android:background o android:background configurado con el valor ?selectableItemBackgroundBorderless:

<Button  
    android:layout_width="250dp"
    android:layout_height="70dp"
    android:text="Ripple"
    android:background="?selectableItemBackgroundBorderless"
    />

NOTA: Este atributo sólo está disponible a partir de la API 21.

Errores de compatibilidad

Al emplear este atributo obtendrás un doble comportamiento.

  • Lollipop (API 21)

  • Por debajo de API 21

¿Cómo se personaliza?

I. Crea un Ripple personalizado ripple.xml en la carpeta drawable de tu aplicación.

<ripple android:color="#ff00ff00">  
   <item android:drawable="@android:color/black" />
</ripple>  

II. Empléalo como valor en los atributos android:background o android:foreground en tus vistas.

<Button  
    android:layout_width="250dp"
    android:layout_height="70dp"
    android:background="@android:color/white"
    android:foreground="@drawable/ripple"
    />

<Button  
    android:layout_width="250dp"
    android:layout_height="70dp"
    android:layout_marginTop="16dp"
    android:background="@android:color/white"
    android:foreground="@drawable/ripple"
    />

<Button  
    android:layout_width="250dp"
    android:layout_height="70dp"
    android:layout_marginTop="16dp"
    android:background="@android:color/white"
    android:foreground="@drawable/ripple"
    />

Nota:. En la raíz, junto al tag ripple debes definir el color que tendrá el efecto, y dentro del mismo los items sobre los que quieres que se dibuje.

Si no incluimos ningún item dentro del ripple, el efecto se dibujará sobre el primer padre disponible dentro de la jerarquía de vistas, en cuyo caso la región de dibujado podrá exceder los límites del drawable. Lo declararíamos del siguiente modo:

<ripple android:color="#ffff0000" />  

Ripple personalizado con selector

I. Crea un selector ripple_selector.xml en la carpeta drawable con los diferentes estados que manejará el selector.

<?xml version="1.0" encoding="utf-8"?>  
<ripple xmlns:android="http://schemas.android.com/apk/res/android"  
        android:color="@color/pink">
    <item>
        <selector>
            <item android:state_activated="true">
                <color android:color="@color/grey_400"/>
            </item>

            <item>
                <color android:color="@android:color/white"/>
            </item>
        </selector>
    </item>
</ripple>  

II. Aplica el selector a la vista deseada.

<Button  
    android:layout_width="250dp"
    android:layout_height="70dp"
    android:elevation="3dp"
    android:background="@drawable/ripple_selector"
    />

Ripple con máscara

I. Crea un drawable bajo el directorio drawables con un item que contenga el atributo id con el valor @android:id/mask

<?xml version="1.0" encoding="utf-8"?>  
<ripple xmlns:android="http://schemas.android.com/apk/res/android"  
        android:color="@color/pink"
    >
    <item android:id="@android:id/mask">
        <shape android:shape="oval">
            <solid android:color="?android:colorAccent"/>
        </shape>
    </item>
</ripple>  

II. Añade este drawable como foreground o background de tu vista:

<Button  
    android:layout_width="250dp"
    android:layout_height="70dp"
    android:background="@drawable/ripple_mask"
    android:text="View"
    />

NOTA: Gracias a la máscara podemos hacer algunos tricks como el de pintar un ripple sobre un fondo transparente.