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

desarrollador de Android
fuente
2
github.com/traex/RippleEffect prueba esto
Aprendizaje rápido
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>
vive el amor
fuente
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.

enlace
fuente
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.

Anrimian
fuente
¿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>
Thomas R.
fuente
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

Dipakk Sharma
fuente
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.

Volodymyr Yatsykiv
fuente
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"

100RaBH
fuente
1

Tratar:

android:background="@android:color/transparent"
android:clickable="true"
android:focusable="true"
android:foreground="?actionBarItemBackground"
duduCMT
fuente
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>
Aminul Haque Aome
fuente
0

solo agrega este artículo en tu

           <ImageButton
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="?android:attr/actionBarItemBackground"
                app:srcCompat="@drawable/ic_arrow_drop_down_black_24dp" />
Ali Eslami
fuente
1
Parece idéntico a esto: stackoverflow.com/a/54440773/878126 .
desarrollador de Android
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
}
mihails.kuzmins
fuente
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