Pulsante Android standard con un colore diverso


735

Vorrei cambiare leggermente il colore di un pulsante Android standard per abbinare meglio il marchio di un cliente.

Il modo migliore che ho trovato per fare questo finora è cambiare il Buttondrawable nel drawable che si trova in 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>

Ma per farlo è necessario creare tre diversi disegni estraibili per ciascun pulsante che voglio personalizzare (uno per il pulsante di riposo, uno per la messa a fuoco e uno per la pressione). Sembra più complicato e non SECCO del necessario.

Tutto quello che voglio davvero fare è applicare una sorta di trasformazione del colore al pulsante. C'è un modo più semplice per cambiare il colore di un pulsante di quello che sto facendo?


Risposte:


724

Ho scoperto che tutto ciò può essere fatto in un file abbastanza facilmente. Inserisci qualcosa come il seguente codice in un file denominato custom_button.xmle quindi imposta background="@drawable/custom_button"nella vista dei pulsanti:

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

43
Funziona bene per il colore di sfondo: puoi impostare il colore del testo allo stesso modo?
Rachel,

8
Questo mi dà "Error: No resource found that matches the given name (at 'color' with value '@color/yellow1')" Questi riferimenti ai colori incorporati? mi sembra di aver bisogno di un res / valori / color.xml per farlo funzionare
Harry Wood,

8
@HarryWood devi definire quei colori nel tuo res / valori / colors.xml. In alternativa, sostituiscili con "# ff0000", "# 00ff00", a scopo di test @ cfarm54 Quel file deve essere inserito nella cartella res / drawable / custom_button.xml @emmby Grazie per lo snippet di codice!
espinchi,

17
Ottimo puntatore, grazie! Nota anche per le altre persone là fuori che provano questo, l'ordine degli elementi nel selettore è significativo. Se si inserisce <item> senza filtri di stato per primi nel file, questo sostituisce il resto.
mikerowehl,

9
per farlo funzionare, inserisci custom_button.xml nella tua cartella res / "drawable" - e crea un file res / valori / colors.xml con questi contenuti: stackoverflow.com/questions/3738886/… - cambia i nomi dei colori in entrambi i file per farlo funzionare
sami,

308

Seguendo la risposta di Tomasz, puoi anche impostare a livello di codice la tonalità dell'intero pulsante usando la modalità di moltiplicazione PorterDuff. Questo cambierà il colore del pulsante anziché solo la tinta.

Se inizi con un pulsante grigio standard:

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

ti darà un pulsante ombreggiato rosso,

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

ti darà un pulsante verde, ecc., dove il primo valore è il colore in formato esadecimale.

Funziona moltiplicando il valore del colore del pulsante corrente per il valore del colore. Sono sicuro che puoi fare molto di più con queste modalità.


2
Wow, l'ho appena provato ed è assolutamente fantastico. Grazie! Ti capita di sapere se c'è un modo per farlo tramite XML in qualche modo?
emmby,

4
Ragazzi, controllate su HTC Desire! Hanno diversi pulsanti standard. I miei pulsanti che usano questo codice sembrano spaventosi QUANDO impostando un certo layout_width come "40dp". Con "wrap_content" va bene.
OneWorld,

5
Confermata, questa soluzione non funziona molto bene
sull'interfaccia

19
Eclipse non mostra questo come una possibile soluzione:import android.graphics.PorterDuff;
Someone Somewhere,

2
Qualcuno ha avuto problemi con questo non funziona in ICS? Per me non sembra funzionare sull'emulatore o sul telefono.
Stev_k,

149

Mike, potresti essere interessato ai filtri colorati.

Un esempio:

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

prova questo per ottenere il colore che desideri.


Prova a passare null nel metodo setColorFilter. Non l'ho provato ma dovrebbe funzionare.
Tomasz,

6
@Pacerier da annullare: button.getBackground (). ClearColorFilter ();
Stan Kurdziel,

3
Consiglio di scegliere un colore usando la classe Colore: developer.android.com/reference/android/graphics/Color.html
Mugen,

Perfetto per temi scuri! Suppongo che l'altra risposta migliore (setColorFilter (0xFFFF0000, PorterDuff.Mode.MULTIPLY)) funzioni meglio per i temi chiari.
java.is.for.desktop,

85

Questa è la mia soluzione che funziona perfettamente a partire da API 15 . Questa soluzione mantiene tutti gli effetti di clic sui pulsanti predefiniti, come materiale RippleEffect. Non l'ho testato su API inferiori, ma dovrebbe funzionare.

Tutto quello che devi fare è:

1) Crea uno stile che cambia solo colorAccent:

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

Ti consiglio di utilizzare ThemeOverlay.AppCompato il tuo principale AppThemecome genitore, per mantenere il resto dei tuoi stili.

2) Aggiungi queste due righe al tuo buttonwidget:

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

A volte il tuo nuovo colorAccentnon viene mostrato in Android Studio Preview, ma quando avvii la tua app sul telefono, il colore cambierà.


Widget Pulsante di esempio

<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" />

Pulsante campione con colore personalizzato


1
Cosa fa questa linea? "style =" @ style / Widget.AppCompat.Button.Colored ""
Charles Li

2
Questo mi ha aiutato a capire la differenza tra stile e tema. Grazie.
rpattabi,

2
La risposta accettata è corretta ma troppo vecchia. Questa è una risposta semplice e aggiornata.
正宗 白 布鞋

Il problema con questa risposta è che l'impostazione colorAccentinfluenza più del semplice sfondo del pulsante.
Blcknx,

@Blcknx Cosa ad esempio?
RediOne1

61

È ora possibile utilizzare anche del appcompat-v7 AppCompatButton con l' backgroundTintattributo:

<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"/>

4
Non ha funzionato per me usando lo spazio dei nomi "android:". Ma ha funzionato quando ho usato lo spazio dei nomi "app:".
David Velasquez,

@DavidVelasquez Che ha funzionato anche per me su Android Lollipop mentre Android: lo spazio dei nomi non ha cambiato nulla. Grazie per l'aiuto!
Avinash Prabhakar,

Questa è la soluzione più semplice e dovrebbe essere la risposta accettata. Usando Android: backgroundTint funziona per me.
Ramashish Baranwal,

1
Deve essere app:backgroundTintinvece di android:backgroundTintquando si utilizza AppCompat.
Hafez Divandari,

23

Mi piace il suggerimento sul filtro colorato nelle risposte precedenti di @conjugatedirection e @Tomasz; Tuttavia, ho scoperto che il codice fornito finora non è stato applicato così facilmente come mi aspettavo.

Innanzitutto, non è stato menzionato dove applicare e cancellare il filtro colorato. È possibile che ci siano altri buoni posti per farlo, ma quello che mi è venuto in mente era un OnTouchListener .

Dalla mia lettura della domanda originale, la soluzione ideale sarebbe quella che non implichi alcuna immagine. La risposta accettata utilizzando custom_button.xml da @emmby è probabilmente una soluzione migliore rispetto ai filtri colorati se questo è il tuo obiettivo. Nel mio caso, sto iniziando con un'immagine png di un designer dell'interfaccia utente di come dovrebbe essere il pulsante. Se imposto lo sfondo del pulsante su questa immagine, il feedback di evidenziazione predefinito verrà perso completamente. Questo codice sostituisce quel comportamento con un effetto di oscuramento programmatico.

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();
    }
});

L'ho estratto come una classe separata per l'applicazione a più pulsanti - mostrato come classe interna anonima solo per avere l'idea.


È stata un'ottima soluzione! Principalmente lo stesso effetto che ottieni su iOS per impostazione predefinita, che è ciò che piace ai designer :-)
Christer Nordvik,

ho provato questo con 2 pulsanti nella stessa schermata con lo stesso sfondo e l'effetto si applica a entrambi i pulsanti Touch
Pippo

16

Se stai creando pulsanti colorati con XML, puoi rendere il codice un po 'più pulito specificando lo stato attivo e premuto in un file separato e riutilizzandoli. Il mio pulsante verde è simile al seguente:

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

1
simpatico. come si può fare in modo che lo stato focalizzato e premuto faccia riferimento alle definizioni Android standard per i pulsanti?
larham1,

Sono abbastanza sicuro che non lo fai poiché i pulsanti Android standard sono implementati come bitmap a 9 patch.
haemish

12

La soluzione più breve che funziona con qualsiasi versione di Android:

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

Note / Requisiti :

  • Usa lo app:spazio dei nomi e non lo android:spazio dei nomi!
  • versione dell'appcompat> 24.2.0

    dipendenze {compilare 'com.android.support:appcompat-v7:25.3.1'}

Spiegazione : inserisci qui la descrizione dell'immagine


1
È interessante notare che per me app:backgroundTint="@color/my_color"non ha funzionato. android:backgroundTint="@color/my_color"ha funzionato perfettamente però.
Igor,

Questa è la soluzione più breve e pulita per me e questo è tutto.
Marty,

11

Sto usando questo approccio

style.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>

Come puoi vedere dall'alto, sto usando uno stile personalizzato per il mio pulsante. Il colore del pulsante corrisponde al colore dell'accento. Trovo che questo sia un approccio molto migliore rispetto all'impostazione android:backgroundpoiché non perderò l'effetto a catena fornito da Google.


8

Ora c'è un modo molto più semplice: android-holo-colors.com

Ti permetterà di cambiare facilmente i colori di tutti i drawable holo (pulsanti, spinner, ...). Si seleziona il colore e quindi si scarica un file zip contenente disegni estraibili per tutte le risoluzioni.


8

Usalo in questo modo:

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

4

In <Button>uso android:background="#33b5e5". o meglioandroid:background="@color/navig_button"


3

La libreria dei componenti DroidUX ha un ColorButtonwidget il cui colore può essere cambiato facilmente, sia tramite definizione xml sia a livello di programmazione in fase di esecuzione, quindi puoi anche consentire all'utente di impostare il colore / tema del pulsante se la tua app lo consente.



2

Puoi impostare il tema del tuo pulsante su questo

<style name="AppTheme.ButtonBlue" parent="Widget.AppCompat.Button.Colored">
 <item name="colorButtonNormal">@color/HEXColor</item>
 <item name="android:textColor">@color/HEXColor</item>
</style>

1

Un modo semplice è semplicemente definire una classe Button personalizzata che accetta tutte le proprietà che desideri come raggio, gradiente, colore stampato, colore normale ecc. E poi usale nei tuoi layout XML invece di impostare lo sfondo usando XML. Un campione è qui

Ciò è estremamente utile se si hanno molti pulsanti con le stesse proprietà come raggio, colore selezionato ecc. È possibile personalizzare il pulsante ereditato per gestire queste proprietà aggiuntive.

Risultato (non è stato utilizzato alcun selettore di sfondo).

Pulsante normale

Immagine normale

Pulsante premuto

inserisci qui la descrizione dell'immagine


0

Il modo in cui eseguo un pulsante con uno stile diverso che funziona abbastanza bene è di sottoclassare l'oggetto Button e applicare un filtro colore. Questo gestisce anche gli stati abilitati e disabilitati applicando un alfa al pulsante.

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

valori \ styles.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>

poi:

<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" />

risultato


0

Secondo le linee guida per la progettazione dei materiali, è necessario utilizzare lo stile come sotto il codice

<style name="MyButton" parent="Theme.AppCompat.Light>
    <item name="colorControlHighlight">#F36F21</item>
    <item name="colorControlHighlight">#FF8D00</item>
</style>

e nel layout aggiungi questa proprietà al tuo pulsante

    android:theme="@style/MyButton"

0

È semplice ... aggiungi questa dipendenza nel tuo progetto e crea un pulsante con 1. Qualsiasi forma 2. Qualsiasi colore 3. Qualsiasi bordo 4. Con effetti materiali

https://github.com/manojbhadane/QButton

<com.manojbhadane.QButton
       android:layout_width="match_parent"
       android:layout_height="wrap_content"
       android:text="OK"
       app:qb_backgroundColor="@color/green"
       app:qb_radius="100"
       app:qb_strokeColor="@color/darkGreen"
       app:qb_strokeWidth="5" />
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.