¿Agregar efecto de onda a mi botón con el color de fondo del botón?

125

¡Creé un botón y quiero agregar un efecto dominó a ese botón!

Creé un archivo XML de botón bg: (bg_btn.xml)

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<gradient android:startColor="#FFFFFF" android:endColor="#00FF00" android:angle="270" />
<corners android:radius="3dp" />
<stroke android:width="5px" android:color="#000000" />
</shape>

Y este es mi archivo de efecto dominó: (ripple_bg.xml)

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

Y este es mi botón que quiero agregar efecto dominó:

<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="@+id/button"
android:layout_centerHorizontal="true"
android:layout_marginTop="173dp"
android:textColor="#fff"
android:background="@drawable/ripple_bg"
android:clickable="true" />

Pero después de agregar el fondo del botón de efecto dominó es transparente, y el botón se muestra solo cuando se hace clic, de esta manera:

Antes de hacer clic

Al hacer clic

Pero necesito el color de fondo del botón y el efecto de onda, encontré parte de este código en diferentes blogs de Stack Overflow, ¡pero aún así no funciona!

rakcode
fuente
haga capturas de pantalla mucho más pequeñas la próxima vez ... (
cambie el
@ user25, también puede agregar un lo mal enlace de la imagen. (ver mi edición)
Suragch

Respuestas:

154

Aquí hay otro xml dibujable para aquellos que desean agregar todo el fondo degradado, el radio de la esquina y el efecto dominó:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="@color/colorPrimaryDark">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorPrimaryLight"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="@dimen/button_radius_large" />
        </shape>
    </item>
</ripple>

Agregue esto al fondo de su botón.

<Button
    ...
    android:background="@drawable/button_background" />
Pei
fuente
44
@pei ¿Cómo obtienen esta información? Quiero decir, ¿cómo sabes que hay un elemento XML llamado ondulación para hacer este trabajo?
1
Es uno de los conceptos utilizados en el diseño de materiales. Comience a escribir una nueva etiqueta raíz en un xml dibujable en Android Studio, entonces debería poder ver todas las etiquetas disponibles, incluidas ripple.
Pei
1
¿Cuál es el uso del elemento de máscara?
Prashant
10
esto requiere un nivel 21 de API
M.kazem Akhgary
2
funciona pero no se explica cómo funciona. debe estar relacionado con la identificación del artículo. Debe ser referenciado.
Oiyio
155

Agregue el atributo de "?attr/selectableItemBackground"su vista android:foregroundsi ya tiene un fondo junto con android:clickable="true".

barra invertidaN
fuente
no siempre funciona, pero puede agregar un fondo al efecto dominó como se señala en los comentarios de la respuesta aceptada
Tyler el
Tuve que usar esta solución ya que he usado un fondo personalizado para mi botón. Funcionó muy bien.
bnayagrawal
@ROAR, es cierto, pero al menos: "Esto no es un error; la aplicación simplemente ignorará el atributo. Sin embargo, si el atributo es importante para la apariencia o funcionalidad de su aplicación, debería considerar encontrar una forma alternativa de lograr el mismo resultado con solo los atributos disponibles, y luego opcionalmente puede crear una copia del diseño en una carpeta layout-vNN que se utilizará en API NN o superior, donde puede aprovechar el atributo más nuevo ". Por lo tanto, funciona bien en dispositivos por encima de API 23 y se ignora cuando se muestra a continuación (solo podemos tools:ignore="UnusedAttribute).
JorgeAmVF
sin la biblioteca de soporte de Android, sería ?android:attr/selectableItemBackground(en android:attrlugar de attr)
Fin de semana
1
android:foregroundatributo no tiene efecto en niveles de API inferiores a 23
Vadim Kotov
67

Agregar efecto de onda / animación a un botón de Android

Simplemente reemplace el atributo de fondo del botón con android: background = "? Attr / selectableItemBackground" y su código se verá así.

      <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="?attr/selectableItemBackground"
        android:text="New Button" />

Otra forma de agregar efecto dominó / animación a un botón de Android

Con este método, puede personalizar el color del efecto dominó. Primero, debe crear un archivo xml en su directorio de recursos dibujables. Cree un archivo ripple_effect.xml y agregue el siguiente código. res / drawable / ripple_effect.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="#f816a463"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="#f816a463" />
        </shape>
    </item>
</ripple>

Y establezca el fondo del botón en el archivo de recursos extraíble anterior

<Button
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/ripple_effect"
    android:padding="16dp"
    android:text="New Button" />
Jigar Patel
fuente
1
Para mí, el efecto dominó no apareció. era solo un interruptor de color para el botón: / Mi versión de Android es 5.1.1, por lo que debería funcionar. ¿Podrías ayudar? Seguí tus pasos
UrviG
android: el color debe ser diferente del mástil android: color, o desea ver el efecto
dominó
2
si desea un fondo, simplemente agregue otro elemento a la onda, como: <item android: drawable = "? attr / colorPrimary" />
Tyler
36

Además de la solución de Jigar Patel , agréguelo a ripple.xml para evitar el fondo transparente de los botones.

<item
    android:id="@android:id/background"
    android:drawable="@color/your-color" />

Xml completo :

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/your-color"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/your-color" />
        </shape>
    </item>
    <item
        android:id="@android:id/background"
        android:drawable="@color/your-color" />
</ripple>

Use este ripple.xml como fondo en su botón:

android:background="@drawable/ripple"
Sudheesh R
fuente
2
No necesitábamos usar el <item android:id="@android:id/mask"> [...]. A menos que quieras una máscara ovalada. ¡Gracias por tu respuesta!
Filipe Brito
¿Qué hace este <item android: id = "@ android: id / mask"> de todos modos, creé 2 elementos similares con y sin ese atributo, y se ven exactamente iguales
Sartheris Stormhammer
@SartherisStormhammer de documentos oficiales: si se establece una capa de máscara, el efecto dominó se enmascarará contra esa capa antes de que se dibuje sobre el compuesto de las capas secundarias restantes. Si no se establece una capa de máscara, el efecto dominó se enmascara contra el compuesto de las capas secundarias. Este es el enlace, developer.android.com/reference/android/graphics/drawable/…
Sudheesh R
@SudheeshR que solo lo hace más confuso
Sartheris Stormhammer
@SartherisStormhammer De esa documentación oficial Creo que está bastante claro. El efecto dominó dibujará sobre capas secundarias / enmascaradas. Por favor, lea el documento nuevamente, obtendrá el punto.
Sudheesh R
33

Cuando el botón tiene un fondo del dibujable, podemos agregar un efecto dominó al parámetro de primer plano. Verifique que el código siguiente funcione para mi botón con un fondo diferente

    <Button
    android:layout_width="wrap_content"
    android:layout_height="40dp"
    android:gravity="center"
    android:layout_centerHorizontal="true"                                                             
    android:background="@drawable/shape_login_button"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:text="@string/action_button_login"
     />

Agregue el siguiente parámetro para el efecto dominó

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

Para referencia, consulte el siguiente enlace https://jascode.wordpress.com/2017/11/11/how-to-add-ripple-effect-to-an-android-app/

Jasmine John
fuente
2
Atributo android: primer plano no tiene efecto en los niveles API inferiores a 23
Ali Khaki
1
Un inconveniente de este enfoque es que, aunque el fondo de mi botón era ovalado, la ondulación se propagó hasta los bordes rectangulares.
iCantC
14

AppCompat v7 +

Si no prefijas con ?android:tu aplicación, se bloqueará.

Debe usar "?android:attr/selectableItemBackground"o "?android:attr/selectableItemBackgroundBorderless", según su preferencia. Yo prefiero Borderless.

Puede ponerlo en android:backgroundo android:foregroundpara mantener las propiedades existentes.

El elemento debe tener android:clickable="true"y android:focusable="true"para que esto funcione, pero muchos elementos, como los botones, los tienen truepor defecto.

<Button
    ...
    android:background="@color/white"
    android:foreground="?android:attr/selectableItemBackgroundBorderless"
/>
<TextView
    ...
    android:background="?android:attr/selectableItemBackgroundBorderless"
    android:clickable="true"
    android:focusable="true"
/>

Programáticamente (Java)

TypedValue value = new TypedValue();
context.getTheme().resolveAttribute(android.R.attr.selectableItemBackground, value, true);
myView.setBackgroundResource(value.resourceId);
myView.setFocusable(true); // If needed for view type

Programáticamente (Kotlin)

val value = TypedValue()
context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
myView.setBackgroundResource(value.resourceId)
myView.setFocusable(true) // If needed for view type

Función de extensión reutilizable de Kotlin

myView.ripple()

fun View.ripple(): View {
    val value = TypedValue()
    context.theme.resolveAttribute(android.R.attr.selectableItemBackground, value, true)
    setBackgroundResource(value.resourceId)
    isFocusable = true // Required for some view types
    return this
}
Gibolt
fuente
7

Agregar atributos de primer plano y clics funcionó para mí.

<Button
    ... 
    android:background="@color/your_color"
    android:foreground="?attr/selectableItemBackgroundBorderless"
    android:clickable="true" />
Ashwin
fuente
6

Además de Sudheesh R

Agregue Ripple Effect / Animation a un botón de Android con forma de rectángulo de botón con esquina

Cree un archivo xml res / drawable / your_file_name.xml

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:color="@color/colorWhite"
    tools:targetApi="lollipop">
    <item android:id="@android:id/mask">
        <shape android:shape="rectangle">
            <solid android:color="@color/colorPrimaryDark" />
            <corners android:radius="50dp" />
        </shape>
    </item>

    <item android:id="@android:id/background">
        <shape android:shape="rectangle">
            <gradient
                android:angle="90"
                android:endColor="@color/colorAccent"
                android:startColor="@color/colorPrimary"
                android:type="linear" />
            <corners android:radius="50dp" />
        </shape>
    </item>
</ripple>
Digvijay Machale
fuente
4

Cuando usa android: background, está reemplazando gran parte del estilo y la apariencia de un botón con un color en blanco.

Actualización: a partir de la versión 23.0.0 de AppCompat, hay un nuevo Widget.AppCompat.Button.Un estilo de color que utiliza el colorButtonNormal de su tema para el color deshabilitado y colorAccent para el color habilitado.

Esto le permite aplicarlo a su botón directamente a través de

<Button
 ...
style="@style/Widget.AppCompat.Button.Colored" />

Puede usar un dibujable en su directorio v21 para su fondo como:

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
    android:color="?attr/colorControlHighlight">
<item android:drawable="?attr/colorPrimary"/>
</ripple>

Esto asegurará que su color de fondo sea? Attr / colorPrimary y tenga la animación de ondulación predeterminada usando el? Attr / colorControlHighlight predeterminado (que también puede configurar en su tema si lo desea).

Nota: deberá crear un selector personalizado por menos de v21:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/primaryPressed"            android:state_pressed="true"/>
<item android:drawable="@color/primaryFocused" android:state_focused="true"/>
<item android:drawable="@color/primary"/>
</selector>
Atman Bhatt
fuente
estoy usando minSDK lvl 21
rakcode
no hay una carpeta dibujable v21, solo una carpeta esa carpeta en sí misma carpeta
v21
Sí, también utilicé esta API, si utilizo esta API después de hacer clic en mi aplicación se bloquea
rakcode
En realidad, estoy probando mi aplicación en mi teléfono con el modo de depuración, y mi sistema operativo es CyanogenMod13 (Android 6, Marshmellow)
rakcode
4

prueba esto

<Button
            android:id="@+id/btn_location"
            android:layout_width="121dp"
            android:layout_height="38dp"
            android:layout_gravity="center"
            android:layout_marginBottom="24dp"
            android:layout_marginTop="24dp"
            android:foreground="?attr/selectableItemBackgroundBorderless"
            android:clickable="true"
            android:background="@drawable/btn_corner"
            android:gravity="center_vertical|center_horizontal"
            android:paddingLeft="13dp"
            android:paddingRight="13dp"
            android:text="Save"
            android:textColor="@color/color_white" />
Raveendra
fuente
4

Un enfoque simple 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>
Adam Hurwitz
fuente
3

Solo usa :

android:backgroundTint="#f816a463"

En vez de:

android:background="#f816a463"

No olvides cambiar tu Buttonaandroid.support.v7.widget.AppCompatButton

Gilad Shapira
fuente
1
Lo malo es que si necesita un botón para llenar al 100% la pantalla horizontal, no lo hará.
Filipe Brito
1

Una solución alternativa al uso de <ripple> etiqueta (que personalmente prefiero no hacer, porque los colores no son "predeterminados"), es la siguiente:

Cree un dibujo para el fondo del botón e inclúyalo <item android:drawable="?attr/selectableItemBackground">en<layer-list>

Luego (y creo que esta es la parte importante) se establece programáticamente backgroundResource(R.drawable.custom_button)en su instancia de botón.

Actividad / Fragmento

Button btn_temp = view.findViewById(R.id.btn_temp);
btn_temp.setBackgroundResource(R.drawable.custom_button);

Diseño

<Button
    android:id="@+id/btn_temp"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@drawable/custom_button"
    android:text="Test" />

custom_button.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white" />
            <corners android:radius="10dp" />
        </shape>
    </item>
    <item android:drawable="?attr/selectableItemBackground" />
</layer-list>
Aidan Host
fuente
¿Por qué debería establecer programáticamente backgroundResource nuevamente, mientras que layout xml define el fondo de Button?
SunnyShiny9