Colorear botones en Android con Material Design y AppCompat

Antes de la actualización de AppCompat salió hoy, pude cambiar el color de los botones en Android L, pero no en las versiones anteriores. Después de incluir la nueva actualización de AppCompat, no puedo cambiar el color de ninguna de las versiones, cuando pruebo el botón desaparece. ¿Alguien sabe cómo cambiar el color del botón?

Las siguientes imágenes muestran lo que quiero lograr:

Imagen que muestra el resultado deseado

El botón blanco es el predeterminado, el rojo es lo que quiero.

Esto es lo que estaba haciendo anteriormente para cambiar el color de los botones en el styles.xml :

 <item name="android:colorButtonNormal">insert color here</item> 

Y hacerlo dinámicamente:

 button.getBackground().setColorFilter(getResources().getColor(insert color here), PorterDuff.Mode.MULTIPLY); 

También @android:style/Theme.Material.Light.DarkActionBar el tema padre de @android:style/Theme.Material.Light.DarkActionBar a Theme.AppCompat.Light.DarkActionBar

Oficialmente fijado en la Biblioteca de Apoyo Rev.22 (Vie 13 de Marzo de 2015). Ver el problema de código de Google relevante:

https://code.google.com/p/android/issues/detail?id=78428

Ejemplo de uso

Theme.xml:

 <item name="colorButtonNormal">@color/button_color</item> 

V21 / theme.xml

 <item name="android:colorButtonNormal">@color/button_color</item> 

Editar (22.06.2016):

Appcompat biblioteca comenzó a apoyar los botones de material después de haber publicado la respuesta original. En este post se puede ver la implementación más fácil de los botones elevados y planos.

Original Respuesta:

Dado que AppCompat no admite el botón todavía puede utilizar xml como fondos. Para hacer que he echado un vistazo al código fuente de la Android y encontró los archivos relacionados para los botones de estilo de material.

1 – Mirar la puesta en práctica original del botón material de la fuente.

Echa un vistazo a la btn_default_material.xml en el código fuente android .

Puede copiar el archivo en su carpeta projects drawable-v21. Pero no toque el color attr aquí. El archivo que debe cambiar es el segundo archivo.

Drawable-v21 / custom_btn.xml

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

2 – Obtener la forma del botón de material original

Como te das cuenta de que hay una forma utilizada dentro de este dibujable que se puede encontrar en este archivo del código fuente .

 <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="@dimen/button_inset_horizontal_material" android:insetTop="@dimen/button_inset_vertical_material" android:insetRight="@dimen/button_inset_horizontal_material" android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/control_corner_material" /> <solid android:color="?attr/colorButtonNormal" /> <padding android:left="@dimen/button_padding_horizontal_material" android:top="@dimen/button_padding_vertical_material" android:right="@dimen/button_padding_horizontal_material" android:bottom="@dimen/button_padding_vertical_material" /> </shape> 

3 – Obtención de las dimensiones del botón de material

Y en este archivo hay algunas dimensiones utilizadas en el archivo que puede encontrar aquí . Puede copiar todo el archivo y ponerlo en su carpeta de valores . Esto es importante para aplicar el mismo tamaño (que se utiliza en los botones de material) a todos los botones

4 – Crear otro archivo para las versiones antiguas

Para las versiones anteriores, debe tener otro dibujable con el mismo nombre. Estoy poniendo directamente los elementos en línea en lugar de hacer referencia. Es posible que desee hacer referencia a ellos. Pero de nuevo, lo más importante son las dimensiones originales del botón material.

Drawable / custom_btn.xml

  <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <!-- pressed state --> <item android:state_pressed="true"> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="@dimen/button_inset_horizontal_material" android:insetTop="@dimen/button_inset_vertical_material" android:insetRight="@dimen/button_inset_horizontal_material" android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/control_corner_material" /> <solid android:color="@color/PRESSED_STATE_COLOR" /> <padding android:left="@dimen/button_padding_horizontal_material" android:top="@dimen/button_padding_vertical_material" android:right="@dimen/button_padding_horizontal_material" android:bottom="@dimen/button_padding_vertical_material" /> </shape> </inset> </item> <!-- focused state --> <item android:state_focused="true"> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="@dimen/button_inset_horizontal_material" android:insetTop="@dimen/button_inset_vertical_material" android:insetRight="@dimen/button_inset_horizontal_material" android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/control_corner_material" /> <solid android:color="@color/FOCUSED_STATE_COLOR" /> <padding android:left="@dimen/button_padding_horizontal_material" android:top="@dimen/button_padding_vertical_material" android:right="@dimen/button_padding_horizontal_material" android:bottom="@dimen/button_padding_vertical_material" /> </shape> </inset> </item> <!-- normal state --> <item> <inset xmlns:android="http://schemas.android.com/apk/res/android" android:insetLeft="@dimen/button_inset_horizontal_material" android:insetTop="@dimen/button_inset_vertical_material" android:insetRight="@dimen/button_inset_horizontal_material" android:insetBottom="@dimen/button_inset_vertical_material"> <shape android:shape="rectangle"> <corners android:radius="@dimen/control_corner_material" /> <solid android:color="@color/NORMAL_STATE_COLOR" /> <padding android:left="@dimen/button_padding_horizontal_material" android:top="@dimen/button_padding_vertical_material" android:right="@dimen/button_padding_horizontal_material" android:bottom="@dimen/button_padding_vertical_material" /> </shape> </inset> </item> </selector> 

Resultado

Su botón tendrá efecto de rizo en los dispositivos Lollipop. Las versiones anteriores tendrán exactamente el mismo botón excepto el efecto de rizo. Pero puesto que usted proporciona los drawables para diversos estados, también responderán a los acontecimientos del tacto (como la manera vieja).

Esto se ha mejorado en v23.0.0 de la biblioteca AppCompat con la adición de más temas incluyendo

Widget.AppCompat.Button.Colored

En primer lugar, incluya la dependencia de appCompat si no ha

 compile('com.android.support:appcompat-v7:23.0.0') { exclude group: 'com.google.android', module: 'support-v4' } 

Ahora ya que necesita usar v23 de la app compat, tendrá que dirigirse a SDK-v23 también!

  compileSdkVersion = 23 targetSdkVersion = 23 

En sus values/theme

 <item name="android:buttonStyle">@style/BrandButtonStyle</item> 

En sus values/style

 <style name="BrandButtonStyle" parent="Widget.AppCompat.Button.Colored"> <item name="colorButtonNormal">@color/yourButtonColor</item> <item name="android:textColor">@color/White</item> </style> 

En sus values-v21/style

 <style name="BrandButtonStyle" parent="Widget.AppCompat.Button.Colored"> <item name="android:colorButtonNormal">@color/yourButtonColor</item> <item name="android:textColor">@color/White</item> </style> 

Dado que el tema del botón se basa en Widget.AppCompat.Button.Colored El color del texto en el botón es por defecto blanco!

Pero parece que hay un problema cuando se deshabilita el botón, el botón cambiará su color a gris claro, pero el color del texto seguirá siendo blanco!

Una solución para esto es configurar específicamente el color del texto en el botón a blanco! Como he hecho en el estilo mostrado arriba.

Ahora puedes simplemente definir tu botón y dejar que AppCompat haga el resto 🙂

 <Button android:layout_width="200dp" android:layout_height="48dp" /> 

Estado deshabilitado Estado deshabilitado

Estado habilitado Estado habilitado

En la Biblioteca de soporte de Android 22.1.0, Google hizo que el tono del Button consciente. Por lo tanto, otra forma de personalizar el color de fondo del botón es utilizar el atributo backgroundTint .

Por ejemplo,

 <Button android:id="@+id/add_remove_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:backgroundTint="@color/bg_remove_btn_default" android:textColor="@android:color/white" tools:text="Remove" /> 

Para apoyar los botones de colores, utilice la última biblioteca de AppCompat (> 23.2.1 ) con:

Inflar – XML

AppCompat Widget:

 android.support.v7.widget.AppCompatButton 

Estilo de AppCompat:

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

¡NÓTESE BIEN! Para establecer un color personalizado en xml: utilice la app attr: en lugar de android

( alt+enter o declare xmlns:app="http://schemas.android.com/apk/res-auto" para usar la app )

App : backgroundTint = "@ color / your_custom_color"

Ejemplo:

 <android.support.v7.widget.AppCompatButton style="@style/Widget.AppCompat.Button.Colored" app:backgroundTint="@color/your_custom_color" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Colored Button"/> 

O establecerlo mediante programación – JAVA

  ViewCompat.setBackgroundTintList(your_colored_button, ContextCompat.getColorStateList(getContext(),R.color.your_custom_color)); 

Con la última Biblioteca de Soporte puedes heredar tu actividad de AppCompatActivity , por lo que AppCompatButton tu Button como AppCompatButton y te daremos la oportunidad de AppCompatButton color de cada botón en el diseño usando android:theme="@style/SomeButtonStyle" Donde SomeButtonStyle es:

 <style name="SomeButtonStyle" parent="@android:style/Widget.Button"> <item name="colorButtonNormal">@color/example_color</item> </style> 

Trabajé para mí en 2.3.7, 4.4.1, 5.0.2

Si usted quiere debajo del estilo

Introduzca aquí la descripción de la imagen

Añada este estilo su botón

 style="@style/Widget.AppCompat.Button.Borderless.Colored" 

Si quieres este estilo

Introduzca aquí la descripción de la imagen

Agregar debajo del código

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

La respuesta está en el tema no estilo

El problema es que el color del botón se pega al colorButtonNormal del tema. He intentado cambiar el estilo de muchas maneras diferentes sin suerte. Así que cambié el tema del botón .

Cree un tema con colorButtonNormal y colorPrimary:

 <style name="ThemeAwesomeButtonColor" parent="AppTheme"> <item name="colorPrimary">@color/awesomePrimaryColor</item> <item name="colorButtonNormal">@color/awesomeButtonColor</item> </style> 

Utilice este tema en el botón

 <Button android:id="@+id/btn_awesome" style="@style/AppTheme.Button" android:theme="@style/ThemeAwesomeButtonColor" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/btn_awesome"/> 

El "AppTheme.Button" puede ser cualquier cosa extiende el estilo del botón como aquí uso el color primario para el color de texto:

 <style name="AppTheme.Button" parent="Base.Widget.AppCompat.Button"> ... <item name="android:textColor">?attr/colorPrimary</item> ... </style> 

Y obtendrá el botón en cualquier color que desee que sea compatible con el diseño del material.

Acabo de crear una biblioteca de android, que permite que usted modifique fácilmente el color del botón y el color de la ondulación

https://github.com/xgc1986/RippleButton

 <com.xgc1986.ripplebutton.widget.RippleButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/btn" android:text="Android button modified in layout" android:textColor="@android:color/white" app:buttonColor="@android:color/black" app:rippleColor="@android:color/white"/> 

No es necesario crear un estilo para cada botón que desea con un color diferente, lo que le permite personalizar los colores al azar

Este trabajo para mí con appcompat-v7: 22.2.0 en android + 4.0

En tus estilos.xml

 <style name="Button.Tinted" parent="Widget.AppCompat.Button"> <item name="colorButtonNormal">YOUR_TINT_COLOR</item> <item name="colorControlHighlight">@color/colorAccent</item> <item name="android:textColor">@android:color/white</item> </style> 

En el archivo de diseño

 <Button android:id="@+id/but_next" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/but_continue" android:theme="@style/Button.Tinted" /> 

Diseño:

 <android.support.v7.widget.AppCompatButton style="@style/MyButton" ... /> 

Styles.xml:

 <style name="MyButton" parent="Widget.AppCompat.Button.Colored"> <item name="backgroundTint">@color/button_background_selector</item> <item name="android:textColor">@color/button_text_selector</item> </style> 

Color / button_background_selector.xml:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="false" android:color="#555555"/> <item android:color="#00ff00"/> </selector> 

Color / button_text_selector.xml:

 <?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:state_enabled="false" android:color="#888888"/> <item android:color="#ffffff"/> </selector> 

Para aquellos que utilizan un ImageButton aquí es cómo hacerlo:

En style.xml:

 <style name="BlueImageButton" parent="Base.Widget.AppCompat.ImageButton"> <item name="colorButtonNormal">@color/primary</item> <item name="android:tint">@color/white</item> </style> 

En v21 / style.xml:

 <style name="BlueImageButton" parent="Widget.AppCompat.ImageButton"> <item name="android:colorButtonNormal">@color/primary</item> <item name="android:tint">@color/white</item> </style> 

A continuación, en el archivo de diseño:

 <android.support.v7.widget.AppCompatImageButton android:id="@+id/my_button" android:theme="@style/BlueImageButton" android:layout_width="42dp" android:layout_height="42dp" android:layout_gravity="center_vertical" android:src="@drawable/ic_check_black_24dp" /> 

Si utiliza la solución de estilo con colorButtonNormal , no olvide heredar de Widget.AppCompat.Button.Colored para que el efecto de rizo está funcionando;)

Me gusta

 <style name="CustomButtonStyle" parent="Widget.AppCompat.Button.Colored"> <item name="colorButtonNormal">@android:color/white</item> </style> 

Si sólo desea el botón de material "Plano", puede personalizar su fondo utilizando el atributo selectableItemBackground tal como se explica aquí .

Para mí, el problema era que en Android 5.0 el android:colorButtonNormal no tenía efecto, y en realidad, no había ningún tema del tema (como android:colorAccent ), pero en Android 4.4.3, por ejemplo, lo hizo. El proyecto se ha configurado con compileSdkVersion y targetSdkVersion a 22, por lo que he hecho todos los cambios como @Muhammad Alfaifi sugessted, pero al final, he notado que el problema fue el buildToolsVersion , que no se actualizó. Una vez que cambié a 23.0.1 , todo comienza a funcionar casi como normal. Ahora, el android:colorButtonNormal todavía no tiene efecto, pero al menos el botón reacciona a android:colorAccent , que para mí es aceptable.

Espero que esta pista pueda ayudar a alguien. Nota: he aplicado el estilo directamente al botón, ya que el android:theme=[...] del botón android:theme=[...] también no tuvo efecto.

Una manera de sacar esto le permite simplemente apuntar a un estilo y NO tema todos los botones de su aplicación lo mismo.
En themes.xml agregue un tema

  <style name="Theme.MyApp.Button.Primary.Blue" parent="Widget.AppCompat.Button"> <item name="colorButtonNormal">@color/someColor</item> <item name="android:textColorPrimary">@android:color/white</item> </style> 

Ahora en styles.xml add

  <style name="MyApp.Button.Primary.Blue" parent=""> <item name="android:theme">@style/Theme.MyApp.Button.Primary.Blue</item> </style> 

Ahora en su disposición simplemente apunte al ESTILO en su botón

  <Button ... style="@style/MyApp.Button.Primary.Blue" ... /> 

ACTUALIZAR

Utilice la biblioteca de soporte de diseño (23.2.0) y appcompatwidgets como a continuación

En la Biblioteca de asistencia de Android 22.1 :

Esto se hace automáticamente al inflar los diseños, reemplazando Button con AppCompatButton, TextView con AppCompatTextView, etc., para asegurarse de que cada uno de ellos podría dar tintado. En esta versión, los widgets conscientes del tinte ahora están disponibles para el público, lo que le permite mantener la compatibilidad de tintado incluso si necesita subclase uno de los widgets compatibles.

La lista completa de widgets conscientes del matiz:

 AppCompatAutoCompleteTextView AppCompatButton AppCompatCheckBox AppCompatCheckedTextView AppCompatEditText AppCompatMultiAutoCompleteTextView AppCompatRadioButton AppCompatRatingBar AppCompatSpinner AppCompatTextView 

Diseño de materiales para dispositivos pre-Lollipop :

AppCompat (aka ActionBarCompat) comenzó como un backport de la API de Android 4.0 ActionBar para dispositivos que se ejecutan en Gingerbread, proporcionando una capa de API común encima de la implementación backported y la implementación del framework. AppCompat v21 ofrece una API y un conjunto de funciones actualizado con Android 5.0


En realidad no quería un cambio en mis estilos de botones personalizados, pero desafortunadamente ya no funcionaban.

Mi aplicación tiene una minSdkVersion de 9 y todo funcionó antes.

No sé por qué pero desde que quité el androide: antes del buttonStyle parece funcionar de nuevo

Ahora = trabajando:

<item name="buttonStyle">@style/ButtonmyTime</item>

Antes = sólo botones de material gris:

<item name="android:buttonStyle">@style/ButtonmyTime</item>

No tengo ninguna carpeta spezial para la versión de andver de newver puesto que mis botones son absolutamente planos y deben parecer iguales a través de todas las versiones de android.

Tal vez alguien me puede decir por qué tuve que eliminar el "android:" El ImageButton sigue trabajando con "android:"

 <item name="android:imageButtonStyle">@style/ImageButtonmyTimeGreen</item> 

Después de 2 días buscando respuestas, el tema del botón no funcionó para mí en API <21.

Mi única solución es anular el color de AppCompatButton no sólo con el tema de la aplicación base "colorButtonNormal", sino también la vista backgroundTint como este:

 public class AppCompatColorButton extends AppCompatButton { public AppCompatColorButton(Context context) { this(context, null); } public AppCompatColorButton(Context context, AttributeSet attrs) { this(context, attrs, android.support.v7.appcompat.R.attr.buttonStyle); } public AppCompatColorButton(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); if (TintManager.SHOULD_BE_USED) { setSupportBackgroundTintList(createButtonColorStateList(getContext(), attrs, defStyleAttr)); } } static final int[] DISABLED_STATE_SET = new int[]{-android.R.attr.state_enabled}; static final int[] FOCUSED_STATE_SET = new int[]{android.R.attr.state_focused}; static final int[] PRESSED_STATE_SET = new int[]{android.R.attr.state_pressed}; static final int[] EMPTY_STATE_SET = new int[0]; private ColorStateList createButtonColorStateList(Context context, AttributeSet attrs, int defStyleAttr) { final int[][] states = new int[4][]; final int[] colors = new int[4]; int i = 0; final int themeColorButtonNormal = ThemeUtils.getThemeAttrColor(context, android.support.v7.appcompat.R.attr.colorButtonNormal); /*TypedArray a = context.obtainStyledAttributes(attrs, new int[] { android.R.attr.backgroundTint }, defStyleAttr, 0); final int colorButtonNormal = a.getColor(0, themeColorButtonNormal);*/ TypedArray a = context.obtainStyledAttributes(attrs, android.support.v7.appcompat.R.styleable.View, defStyleAttr, 0); final int colorButtonNormal = a.getColor(android.support.v7.appcompat.R.styleable.View_backgroundTint, themeColorButtonNormal); a.recycle(); final int colorControlHighlight = ThemeUtils.getThemeAttrColor(context, android.support.v7.appcompat.R.attr.colorControlHighlight); // Disabled state states[i] = DISABLED_STATE_SET; colors[i] = ThemeUtils.getDisabledThemeAttrColor(context, android.support.v7.appcompat.R.attr.colorButtonNormal); i++; states[i] = PRESSED_STATE_SET; colors[i] = ColorUtils.compositeColors(colorControlHighlight, colorButtonNormal); i++; states[i] = FOCUSED_STATE_SET; colors[i] = ColorUtils.compositeColors(colorControlHighlight, colorButtonNormal); i++; // Default enabled state states[i] = EMPTY_STATE_SET; colors[i] = colorButtonNormal; i++; return new ColorStateList(states, colors); } } 

A continuación, puede definir el color del botón de esta manera:

 <com.example.views.AppCompatColorButton android:layout_width="match_parent" android:layout_height="wrap_content" android:backgroundTint="#ffff0000" app:backgroundTint="#ffff0000" android:text="Button" android:textColor="@android:color/white" /> 

Para cambiar el color de un solo botón

 ViewCompat.setBackgroundTintList(button, getResources().getColorStateList(R.color.colorId)); 

Esta respuesta de SO me ayudó a llegar a una respuesta https://stackoverflow.com/a/30277424/3075340

Utilizo este método de utilidad para establecer el tinte de fondo de un botón. Funciona con dispositivos pre-lollipop:

 // Set button background tint programmatically so it is compatible with pre-lollipop devices. public static void setButtonBackgroundTintAppCompat(Button button, ColorStateList colorStateList){ Drawable d = button.getBackground(); if (button instanceof AppCompatButton) { // appcompat button replaces tint of its drawable background ((AppCompatButton)button).setSupportBackgroundTintList(colorStateList); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Lollipop button replaces tint of its drawable background // however it is not equal to d.setTintList(c) button.setBackgroundTintList(colorStateList); } else { // this should only happen if // * manually creating a Button instead of AppCompatButton // * LayoutInflater did not translate a Button to AppCompatButton d = DrawableCompat.wrap(d); DrawableCompat.setTintList(d, colorStateList); button.setBackgroundDrawable(d); } } 

Cómo utilizar en código:

 Utility.setButtonBackgroundTintAppCompat(myButton, ContextCompat.getColorStateList(mContext, R.color.your_custom_color)); 

De esta manera, no tiene que especificar un ColorStateList si sólo desea cambiar el tinte de fondo y nada más, pero mantener los efectos de botón bonito y qué no.

Si desea utilizar estilo AppCompat como Widget.AppCompat.Button , Base.Widget.AppCompat.Button.Colored , etc., debe utilizar estos estilos con vistas compatibles de la biblioteca de soporte.

El código siguiente no funciona para los dispositivos pre-lolipop:

 <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:theme="@style/Widget.AppCompat.Button" /> 

Es necesario utilizar AppCompatButton para activar los estilos de AppCompat:

 <android.support.v7.widget.AppCompatButton android:layout_width="wrap_content" android:layout_height="wrap_content" android:theme="@style/Widget.AppCompat.Button" /> 
  • Elementos compartidos de Android con Picasso
  • Cómo configurar un efecto ripple en textview o imageview en Android?
  • Alinear un icono con el icono de la barra de herramientas - Android Material Design
  • ¿Cómo se cambia el color de línea / campo de EditText en TextInputLayout (cuando se llama a setError)?
  • ¿Cómo utilizar ItemAnimator en un RecyclerView?
  • Android: Fotos de Google como Vista de cuadrícula con funcionalidad de zoom
  • Animación como cambiar cuentas en la aplicación de Gmail
  • ¿Cómo cambiar el color de ActionBar al pasar entre fragmentos (diseño de material)?
  • Botón de diseño de material con borde
  • Directrices de diseño - El tamaño no suma
  • ¿Cómo mostrar un cuadro de diálogo en Android con el efecto revelador del diseño de material?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.