Botón estándar de Android 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 manera que he encontrado para hacer esto hasta ahora es cambiar el elemento de diseño de Button al siguiente elemento de diseño ubicado en res/drawable/red_button.xml:

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

Pero esto requiere que crear tres diferentes dibujables para cada botón que desea personalizar (uno para el botón en reposo, uno cuando está centrado, y uno cuando se pulsa). Eso parece más complicado y no SECO que yo necesitar.

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

Author: Catalina, 2009-10-05

18 answers

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

<?xml version="1.0" encoding="utf-8"?>
<selector
    xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_pressed="true" >
        <shape>
            <gradient
                android:startColor="@color/yellow1"
                android:endColor="@color/yellow2"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

    <item android:state_focused="true" >
        <shape>
            <gradient
                android:endColor="@color/orange4"
                android:startColor="@color/orange5"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>

    <item>        
        <shape>
            <gradient
                android:endColor="@color/blue2"
                android:startColor="@color/blue25"
                android:angle="270" />
            <stroke
                android:width="3dp"
                android:color="@color/grey05" />
            <corners
                android:radius="3dp" />
            <padding
                android:left="10dp"
                android:top="10dp"
                android:right="10dp"
                android:bottom="10dp" />
        </shape>
    </item>
</selector>
 698
Author: emmby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 12:59:16

Siguiendo con la respuesta de Tomasz, también puede configurar programáticamente el tono de todo el botón utilizando el modo de multiplicación PorterDuff. Esto cambiará el color del botón en lugar de solo el tinte.

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

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 multiplicando el valor de color del botón actual por su valor de color. Estoy seguro de que también hay mucho más que puedes hacer con estos modos.

 298
Author: conjugatedirection,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-15 02:41:42

Mike, puede que te interesen los filtros de color.

Un ejemplo:

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

Pruebe esto para lograr el color que desea.

 144
Author: Tomasz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-09-05 06:38:29

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

Todo lo que necesitas hacer es:

1) Crea un estilo que solo cambia colorAccent:

<style name="Facebook.Button" parent="ThemeOverlay.AppCompat">
    <item name="colorAccent">@color/com_facebook_blue</item>
</style>

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

2) Añadir estas dos líneas a su button widget:

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

A veces tu nuevo colorAccent no se muestra en la vista previa de Android Studio, pero cuando inicias tu aplicación en el teléfono, el color cambiará.


Widget de botón de muestra

<Button
    android:id="@+id/sign_in_with_facebook"
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:text="@string/sign_in_facebook"
    android:textColor="@android:color/white"
    android:theme="@style/Facebook.Button" />

Botón de muestra con color personalizado

 75
Author: RediOne1,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-07 05:03:14

Ahora también puede usar el AppCompatButton de appcompat-v7 con el atributo backgroundTint:

<android.support.v7.widget.AppCompatButton
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:backgroundTint="#ffaa00"/>
 48
Author: Nilhcem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-03 05:19:45

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 aplicó tan fácilmente como esperaba.

En primer lugar, no se mencionó donde para 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.

De mi lectura de la pregunta original, la solución ideal sería una que no involucre cualquier imagen. La respuesta aceptada usando custom_button.xml de @emmby es probablemente una mejor opción que los filtros de color si ese es tu objetivo. En mi caso, estoy comenzando con una imagen png de un diseñador de interfaz de usuario de lo que se supone que el botón debe ser similar. Si establezco el fondo del botón en 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();
    }
});

He extraído esto como una clase separada para la aplicación a botones múltiples-se muestra como clase interna anónima solo para hacerse una idea.

 22
Author: Stan Kurdziel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-06-17 11:07:25

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

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:state_focused="true" android:drawable="@drawable/button_focused"/>
    <item android:state_pressed="true" android:drawable="@drawable/button_pressed"/>

    <item>
        <shape>
            <gradient android:startColor="#ff00ff00" android:endColor="#bb00ff00" android:angle="270" />
            <stroke android:width="1dp" android:color="#bb00ff00" />
            <corners android:radius="3dp" />
            <padding android:left="10dp" android:top="10dp" android:right="10dp" android:bottom="10dp" />
        </shape>
    </item>

</selector>
 16
Author: haemish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-12-16 11:23:24

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

<Button
     app:backgroundTint="@color/my_color"

Notas / Requisitos :

  • Use el espacio de nombres app:y no el espacio de nombres android:!
  • Appcompat version > 24.2.0

    Dependencias { compile ' com.androide.soporte: appcompat-v7: 25.3.1' }

Explicación: introduzca la descripción de la imagen aquí

 10
Author: user1185087,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-04 12:27:59

Estoy usando este enfoque

Estilo.xml

<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
    <item name="android:colorPrimaryDark">#413152</item>
    <item name="android:colorPrimary">#534364</item>
    <item name="android:colorAccent">#534364</item>
    <item name="android:buttonStyle">@style/MyButtonStyle</item>
</style>

<style name="MyButtonStyle" parent="Widget.AppCompat.Button.Colored">
    <item name="android:colorButtonNormal">#534364</item>
    <item name="android:textColor">#ffffff</item>
</style>

Como puedes ver desde arriba, estoy usando un estilo personalizado para mi botón. El color del botón corresponde al color del acento. Creo que este es un enfoque mucho mejor que establecer android:background ya que no perderé el efecto dominó que proporciona Google.

 9
Author: Kelok Chan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-05 13:23:43

Ahora hay una manera mucho más fácil: android-holo-colors.com

Le permitirá cambiar los colores de todos los elementos de diseño holo (botones, hilanderos,...) facilmente. Seleccione el color y luego descargue un archivo zip que contenga elementos de diseño para todas las resoluciones.

 8
Author: Dalmas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-14 12:45:53

Úsalo de esta manera:

buttonOBJ.getBackground().setColorFilter(Color.parseColor("#YOUR_HEX_COLOR_CODE"), PorterDuff.Mode.MULTIPLY);
 8
Author: IntelliJ Amiya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-14 05:08:40

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

 4
Author: lalitm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-03-01 06:31:52

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

 3
Author: Ricky Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-08-05 12:53:26

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

 3
Author: JRE.exe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-27 13:09:11

Puede establecer el tema de su botón a este

<style name="AppTheme.ButtonBlue" parent="Widget.AppCompat.Button.Colored">
 <item name="colorButtonNormal">@color/HEXColor</item>
 <item name="android:textColor">@color/HEXColor</item>
</style>
 2
Author: Manoj Bhadane,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-07 10:30:57

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

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

Resultado (No se utilizó selector de fondo).

Botón normal

Imagen Normal

Pulsado el botón

introduzca la descripción de la imagen aquí

 1
Author: redDragonzz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-13 14:13:11

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 (e.g. 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 (e.g. 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;
        }
    }

}
 0
Author: Matthew Cawley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-25 08:48:21

Valores\estilos.xml

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
    <item name="colorPrimary">@color/colorPrimary</item>
    <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
    <item name="colorAccent">@color/colorAccent</item>
</style>

<style name="RedAccentButton" parent="ThemeOverlay.AppCompat.Light">
    <item name="colorAccent">#ff0000</item>
</style>

Entonces:

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

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:enabled="false"
    android:text="text" />

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

<Button
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:enabled="false"
    android:text="text"
    android:theme="@style/RedAccentButton" />

resultado

 0
Author: Milan Hlinák,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-06 17:37:10