¿Cómo hacer una ondulación circular en un botón cuando se hace clic en él?


121

Antecedentes

En la aplicación de marcador de Android, cuando comienzas a buscar algo y haces clic en el botón de flecha a la izquierda de EditText, obtienes un efecto dominó circular en él:

ingrese la descripción de la imagen aquí

El problema

Intenté tenerlo también, pero obtuve uno rectangular:

    <ImageButton
        android:id="@+id/navButton"
        android:layout_width="40dp"
        android:layout_height="40dp"
        android:layout_gravity="center_vertical"
        android:layout_marginLeft="8dp"
        android:background="?android:attr/selectableItemBackground"
        android:src="@drawable/search_ic_back_arrow"/>

La pregunta

¿Cómo hago para que el botón tenga un efecto de onda circular al hacer clic? ¿Tengo que crear un nuevo dibujable o hay una forma incorporada para eso?



la posible respuesta está aquí stackoverflow.com/questions/33477025/…
— Amrish Kakadiya

1
Considere cambiar su respuesta seleccionada por la que tenga más votos positivos, ya que en realidad resuelve el problema
— Jeff Barger

@JeffBarger ¿Por qué? Ambos funcionan bien. No hay nadie mejor entre ellos.
— desarrollador de Android

Respuestas:


17

Si ya tiene una imagen de fondo, aquí hay un ejemplo de una onda que parece cercana a selectableItemBackgroundBorderless:

            <ImageButton
                android:id="@+id/btn_show_filter_dialog"
                android:layout_width="24dp"
                android:layout_height="24dp"
                android:background="@drawable/ic_filter_state"/>

ic_filter_state.xml:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:state_pressed="true"
        android:state_enabled="true"
        android:drawable="@drawable/state_pressed_ripple"/>
    <item
        android:state_enabled="true"
        android:drawable="@drawable/ic_filter" />
</selector>

state_pressed_ripple.xml: (opacidad establecida al 10% sobre fondo blanco) 1AFFFFFF

 <?xml version="1.0" encoding="UTF-8"?>    
    <ripple xmlns:android="http://schemas.android.com/apk/res/android">
        <item>
            <shape android:shape="oval">
                <solid android:color="#1AFFFFFF"/>
            </shape>
            <color android:color="#FFF"/>
        </item>
    </ripple>

285

Si está utilizando el tema AppCompat, puede establecer el fondo de la vista como:

android:background="?selectableItemBackgroundBorderless"

Esto agregará una ondulación circular en 21 y arriba y un fondo cuadrado en 21 por debajo.


Agradable. ¿Puedo también establecer el color de alguna manera?
— desarrollador de Android

4
en API 23, el fondo 'up' parece tener la mitad del tamaño en comparación con selectbleItemBackgroundBorderless
— snodnipper

3
Bonita, la mejor respuesta. ty
— Skywalker

1
@androiddeveloper, el color se puede configurar configurando colorControlHighlight como se muestra a continuación en su styles.xml <item name = "colorControlHighlight"> # F00 </item>
— enlace

3
Si lo está utilizando dentro de otros diseños, es posible que también necesite android:clipChildren="false"en los diseños para permitir que la animación se propague.
— Tanasis

82

Otro atributo con efecto de onda redonda, especialmente para la barra de acción:

android:background="?actionBarItemBackground"

UPD : este atributo puede cambiar el color de la ondulación:

<!--somewhere in styles-->
<item name="colorControlHighlight">your_color_here</item>

Pero tenga en cuenta que este atributo se aplica a todos los efectos dominó predeterminados.


¿Alguna forma de personalizarlo? ¿Por ejemplo el color? ¿Quizás algo en estilos? ¿O incluso más específicamente en la propia etiqueta XML de vista?
— desarrollador de Android

No lo sé, hoy resolví este problema y las respuestas anteriores no funcionaron como necesitaba. Supongo que el color se puede personalizar en estilos, pero definitivamente no en la vista.
— Anrimian

1
Este es exactamente el efecto correcto que estoy buscando. Por cierto, ¿puede mencionar dónde encontrar este atributo? Parece que no está documentado.
— Jack Wang

2
Responde a la pregunta de OP. Debe marcarse como la mejor respuesta. +1
— Corbella

2
@MeysamHadigheh ?es un atajo para?attr/
— musooff

47

Cree y establezca una ondulación dibujable como fondo. Algo como esto.

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

Es algo en mi código. Puedes usar tus colores :)
— Thomas R.

¿Cómo usaría el selector predeterminado en caso de que esté en pre-Lollipop? Además, ¿utiliza los mismos colores que el del marcador?
— desarrollador de Android

2
Puede poner el dibujable ondulado en su carpeta drawables-v21. Y para pre L use un simple estado dibujable. Use el mismo nombre de archivo y colóquelo en la carpeta dibujable (predeterminada).
— Thomas R.

2
También puedes crear un estilo. En la carpeta values-v21, cree un nuevo estilo y establezca la ondulación dibujable como fondo. Y para pre L, es decir, en su carpeta de valores styles.xml ponga como fondo el atributo "selectableItemBackground" para el mismo estilo.
— Thomas R.

1
Si desea el mismo color de ondulación que los otros efectos de ondulación predeterminados utilizados en la aplicación, utilice "? Attr / colorControlHighlight" como color.
— alexbchr

27

Simplemente agregue este fondo a su vista

android:background=?android:attr/actionBarItemBackground


18

Puede crear un dibujo de ondulación circular utilizando el android:radiusatributo en xml.

Ejemplo:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="your_color"
    android:radius="your_radius" />

Preste atención, your_radiusdebe ser menor que el ancho y la altura de su vista. Por ejemplo: si tiene una vista con el tamaño 60dp x 60dp your_radiusdebe estar cerca 30dp(ancho / 2 o alto / 2).

Trabaja en Android 5.0 y superior.


3

Si desea archivos XML más genéricos, tengo dos archivos:

1) btn_ripple_background con código:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:state_pressed="true"
    android:state_enabled="true"
    android:drawable="@drawable/ripple_circular_shape"/>
</selector>

2) ripple_circuler_shape con código:

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

finalmente el uso:android:foreground="@drawable/ripple_btn_background"


1

Tratar:

android:background="@android:color/transparent"
android:clickable="true"
android:focusable="true"
android:foreground="?actionBarItemBackground"

1
No publique solo código como respuesta, sino que incluya una explicación de lo que hace su código y cómo resuelve el problema de la pregunta. Las respuestas con una explicación son generalmente de mayor calidad y es más probable que atraigan votos positivos.
— Mark Rotteveel

Más suave que establecer actionBarItemBackground como fondo. Pero aún no es exactamente igual que la animación de la barra de acción en sí.
— coolcool1994

1

Si desea un efecto dominó que no cruce el límite del círculo, puede verificar este código. Funciona perfectamente para mí. Solo recuerde, debe ingresar id = @ android: id / mask en ripple_blue.xml

<ImageButton
    android:id="@+id/send_password_to_mail_image_view"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_blue"
    android:src="@drawable/ic_filter" />

ripple_blue.xml

<ripple
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorRipple">

    <item android:id="@android:id/mask">

        <shape android:shape="oval">
            <solid android:color="@color/colorWindowBackground"/>
        </shape>

    </item>

    <item android:id="@android:id/background">

        <shape android:shape="oval">
            <solid android:color="@color/colorWindowBackground"/>
        </shape>

    </item>

</ripple>

color.xml

<resources xmlns:tools="http://schemas.android.com/tools">
    <color name="colorWindowBackground">#F2F5FC</color>
    <color name="colorRipple">#0288d1</color>
</resources>


0

En Kotlin / Java puede hacer lo siguiente

fun View.applyCircularRippleEffect() {
    val backgroundResId = context.getResource(android.R.attr.actionBarItemBackground)

    if (backgroundResId != 0) {
        setBackgroundResource(backgroundResId)
        isClickable = true
        isFocusable = true
    }
}

// getResource extension
fun Context.getResource(resourceId: Int): Int {
    val out = TypedValue()
    theme.resolveAttribute(resourceId, out, true)

    return out.resourceId
}

context.getResource no encontrado
— Rahul Mandaliya

@RahulMandaliya gracias por el comentario. Mi mal, fue mi método de extensión personalizado. Se agregó a la respuesta
— mihails.kuzmins
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.