Botón Android estándar con un color diferente

Me gustaría cambiar ligeramente el color de un botón estándar de Android para que coincida mejor con la marca de un cliente.

La mejor forma que he encontrado para hacer esto hasta ahora es cambiar el res/drawable/red_button.xml del Button al siguiente dibujante ubicado en res/drawable/red_button.xml :

       

Pero hacer eso requiere que realmente cree tres estilos diferentes para cada botón que quiera personalizar (uno para el botón en reposo, uno cuando está enfocado y uno cuando lo presiona). Eso parece más complicado y no SECO de lo que necesito.

Todo lo que realmente quiero hacer es aplicar algún tipo de transformación de color al botón. ¿Hay una forma más fácil de cambiar el color de un botón que el que estoy haciendo?

Descubrí que todo esto se puede hacer en un archivo con bastante facilidad. Ponga algo así como el siguiente código en un archivo llamado custom_button.xml y luego establezca background="@drawable/custom_button" en su vista de botón:

                            

Siguiendo con la respuesta de Tomasz, también puedes establecer programáticamente el tono de todo el botón usando el modo de multiplicar PorterDuff. Esto cambiará el color del botón en lugar de solo el tinte.

Si comienza con un botón sombreado gris estándar:

 button.getBackground().setColorFilter(0xFFFF0000, PorterDuff.Mode.MULTIPLY); 

le dará un botón sombreado rojo,

 button.getBackground().setColorFilter(0xFF00FF00, PorterDuff.Mode.MULTIPLY); 

le dará un botón sombreado verde, etc., donde el primer valor es el color en formato hexadecimal.

Funciona al multiplicar el valor del color del botón actual por el valor del color. Estoy seguro de que también hay mucho más que puedes hacer con estos modos.

Mike, es posible que te interesen los filtros de color.

Un ejemplo:

 button.getBackground().setColorFilter(new LightingColorFilter(0xFFFFFFFF, 0xFFAA0000)); 

intente esto para lograr el color que desea.

Esta es mi solución, que funciona perfectamente a partir de API 15 . Esta solución mantiene todos los efectos de clic de botón predeterminados, como el material RippleEffect . No lo he probado en API más bajas, pero debería funcionar.

Todo lo que necesitas hacer es:

1) Crea un estilo que solo cambie colorAccent :

  

Recomiendo usar ThemeOverlay.AppCompat o su AppTheme principal como padre, para mantener el rest de sus estilos.

2) Agregue estas dos líneas a su widget de button :

 style="@style/Widget.AppCompat.Button.Colored" android:theme="@style/Facebook.Button" 

En ocasiones, su nuevo colorAccent no se muestra en Android Studio Preview, pero cuando colorAccent su aplicación en el teléfono, el color cambiará.


Widget de botón de muestra

  

Botón de muestra con color personalizado

Ahora también puede usar appCompat-v7’s AppCompatButton con el atributo backgroundTint :

  

Me gusta la sugerencia de filtro de color en respuestas anteriores de @conjugatedirection y @Tomasz; Sin embargo, descubrí que el código proporcionado hasta ahora no se aplicaba tan fácilmente como esperaba.

En primer lugar, no se mencionó dónde aplicar y borrar el filtro de color. Es posible que haya otros buenos lugares para hacer esto, pero lo que me vino a la mente fue un OnTouchListener .

A partir de mi lectura de la pregunta original, la solución ideal sería aquella que no implique ninguna imagen. La respuesta aceptada usando custom_button.xml de @emmby es probablemente una mejor opción que los filtros de color si ese es su objective. En mi caso, estoy empezando con una imagen png de un diseñador de UI de cómo se supone que debe verse el botón. Si configuro el fondo del botón para esta imagen, la retroalimentación de resaltado predeterminada se pierde por completo. Este código reemplaza ese comportamiento con un efecto de oscurecimiento programático.

 button.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: // 0x6D6D6D sets how much to darken - tweak as desired setColorFilter(v, 0x6D6D6D); break; // remove the filter when moving off the button // the same way a selector implementation would case MotionEvent.ACTION_MOVE: Rect r = new Rect(); v.getLocalVisibleRect(r); if (!r.contains((int) event.getX(), (int) event.getY())) { setColorFilter(v, null); } break; case MotionEvent.ACTION_OUTSIDE: case MotionEvent.ACTION_CANCEL: case MotionEvent.ACTION_UP: setColorFilter(v, null); break; } return false; } private void setColorFilter(View v, Integer filter) { if (filter == null) v.getBackground().clearColorFilter(); else { // To lighten instead of darken, try this: // LightingColorFilter lighten = new LightingColorFilter(0xFFFFFF, filter); LightingColorFilter darken = new LightingColorFilter(filter, 0x000000); v.getBackground().setColorFilter(darken); } // required on Android 2.3.7 for filter change to take effect (but not on 4.0.4) v.getBackground().invalidateSelf(); } }); 

Extraje esto como una clase separada para la aplicación a varios botones, que se muestra como clase interna anónima solo para obtener la idea.

Si está haciendo botones de color con XML, puede hacer que el código sea un poco más limpio al especificar el estado enfocado y presionado en un archivo separado y volver a utilizarlos. Mi botón verde se ve así:

              

La solución más corta que funciona con cualquier versión de Android:

 

Notas / requisitos :

  • Use la app: namespace y no android: namespace!
  • versión de appcompat> 24.2.0

    dependencias {comstackr 'com.android.support:appcompat-v7:25.3.1'}

Explicación enter image description here

Estoy usando este enfoque

style.xml

    

Como puede ver desde arriba, estoy usando un estilo personalizado para mi botón. El color del botón corresponde al color de acento. Considero que este es un enfoque mucho mejor que establecer android:background ya que no voy a perder el efecto dominó que ofrece Google.

Hay una manera mucho más fácil ahora: android-holo-colors.com

Te permitirá cambiar los colores de todos los holo drenables (botones, rotuladores, …) fácilmente. Usted selecciona el color y luego descarga un archivo zip que contiene herramientas para todas las resoluciones.

Úselo de esta manera:

 buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY); 

En use android:background="#33b5e5" . o mejor android:background="@color/navig_button"

La biblioteca de componentes DroidUX tiene un widget ColorButton cuyo color se puede cambiar fácilmente, tanto a través de la definición xml como programáticamente en tiempo de ejecución, por lo que incluso puede permitirle al usuario configurar el color / tema del botón si su aplicación lo permite.

También puede utilizar esta herramienta en línea para personalizar su botón http://angrytools.com/android/button/ y usar android:background="@drawable/custom_btn" para definir el botón personalizado en su diseño.

Puede configurar el tema de su botón para esto

  

Una manera fácil es simplemente definir una clase de botón personalizada que acepte todas las propiedades que desee, como el radio, el degradado, el color presionado, el color normal, etc. y luego simplemente use eso en sus diseños XML en lugar de configurar el fondo mediante XML. Una muestra está aquí

Esto es extremadamente útil si tiene muchos botones con las mismas propiedades, como el radio, el color seleccionado, etc. Puede personalizar su botón heredado para manejar estas propiedades adicionales.

Resultado (sin selector de fondo se utilizó).

Botón normal

Imagen normal

Botón presionado

enter image description here

La forma en que hago un botón de estilo diferente que funciona bastante bien es subclasificar el objeto Button y aplicar un filtro de color. Esto también maneja los estados habilitados y deshabilitados aplicando un alfa al botón.

 import android.annotation.TargetApi; import android.content.Context; import android.graphics.Color; import android.graphics.ColorFilter; import android.graphics.LightingColorFilter; import android.graphics.drawable.Drawable; import android.graphics.drawable.LayerDrawable; import android.os.Build; import android.util.AttributeSet; import android.widget.Button; public class DimmableButton extends Button { public DimmableButton(Context context) { super(context); } public DimmableButton(Context context, AttributeSet attrs) { super(context, attrs); } public DimmableButton(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @SuppressWarnings("deprecation") @Override public void setBackgroundDrawable(Drawable d) { // Replace the original background drawable (eg image) with a LayerDrawable that // contains the original drawable. DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d); super.setBackgroundDrawable(layer); } @TargetApi(Build.VERSION_CODES.JELLY_BEAN) @Override public void setBackground(Drawable d) { // Replace the original background drawable (eg image) with a LayerDrawable that // contains the original drawable. DimmableButtonBackgroundDrawable layer = new DimmableButtonBackgroundDrawable(d); super.setBackground(layer); } /** * The stateful LayerDrawable used by this button. */ protected class DimmableButtonBackgroundDrawable extends LayerDrawable { // The color filter to apply when the button is pressed protected ColorFilter _pressedFilter = new LightingColorFilter(Color.LTGRAY, 1); // Alpha value when the button is disabled protected int _disabledAlpha = 100; // Alpha value when the button is enabled protected int _fullAlpha = 255; public DimmableButtonBackgroundDrawable(Drawable d) { super(new Drawable[] { d }); } @Override protected boolean onStateChange(int[] states) { boolean enabled = false; boolean pressed = false; for (int state : states) { if (state == android.R.attr.state_enabled) enabled = true; else if (state == android.R.attr.state_pressed) pressed = true; } mutate(); if (enabled && pressed) { setColorFilter(_pressedFilter); } else if (!enabled) { setColorFilter(null); setAlpha(_disabledAlpha); } else { setColorFilter(null); setAlpha(_fullAlpha); } invalidateSelf(); return super.onStateChange(states); } @Override public boolean isStateful() { return true; } } } 

values ​​\ styles.xml

   

entonces:

     

resultado