Standard Android Button mit einer anderen Farbe


735

Ich möchte die Farbe einer Standard-Android-Schaltfläche leicht ändern, um sie besser an das Branding eines Kunden anzupassen.

Der beste Weg, dies bisher zu tun, besteht darin, das ButtonDrawable in das Drawable zu ändern , das sich in befindet 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>

Dazu muss ich jedoch drei verschiedene Zeichen für jede Schaltfläche erstellen, die ich anpassen möchte (eine für die Schaltfläche in Ruhe, eine beim Fokussieren und eine beim Drücken). Das scheint komplizierter und nicht trocken zu sein, als ich brauche.

Alles, was ich wirklich tun möchte, ist eine Art Farbtransformation auf die Schaltfläche anzuwenden. Gibt es einen einfacheren Weg, um die Farbe einer Schaltfläche zu ändern als ich?


Antworten:


724

Ich habe festgestellt, dass dies alles ziemlich einfach in einer Datei erledigt werden kann. Fügen Sie so etwas wie den folgenden Code in eine Datei mit dem Namen ein custom_button.xmlund legen Sie ihn background="@drawable/custom_button"in Ihrer Schaltflächenansicht fest:

<?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
Das funktioniert gut für Hintergrundfarben - können Sie die Textfarbe auf die gleiche Weise einstellen?
Rachel

8
Dies gibt mir "Error: No resource found that matches the given name (at 'color' with value '@color/yellow1')" Sind diese Verweise auf eingebaute Farben? Anscheinend brauche ich eine res / values ​​/ color.xml, damit das funktioniert
Harry Wood

8
@HarryWood Sie müssen diese Farben in Ihrer res / values ​​/ colours.xml definieren. Alternativ können Sie sie zu Testzwecken durch "# ff0000", "# 00ff00" ersetzen. @ Cfarm54 Diese Datei wird im Ordner res / drawable / custom_button.xml @emmby abgelegt. Vielen Dank für das Code-Snippet!
Espinchi

17
Toller Zeiger, danke! Beachten Sie auch, dass für die anderen Leute, die dies versuchen, die Reihenfolge der Elemente in der Auswahl von Bedeutung ist. Wenn Sie das <item> ohne Statusfilter zuerst in die Datei einfügen, wird der Rest überschrieben.
Mikerowehl

9
Damit dies funktioniert, legen Sie custom_button.xml in Ihrem Ordner res / "drawable" ab und erstellen Sie eine Datei res / values ​​/ color.xml mit folgendem Inhalt: stackoverflow.com/questions/3738886/… - Ändern Sie die Farbnamen in beiden Dateien damit es funktioniert
sami

308

In Anlehnung an Tomasz 'Antwort können Sie den Farbton der gesamten Schaltfläche auch programmgesteuert im PorterDuff-Multiplikationsmodus einstellen. Dadurch wird die Tastenfarbe und nicht nur der Farbton geändert.

Wenn Sie mit einer grau schattierten Standardschaltfläche beginnen:

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

gibt Ihnen einen rot schattierten Knopf,

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

Sie erhalten eine grün schattierte Schaltfläche usw., wobei der erste Wert die Farbe im Hex-Format ist.

Es funktioniert, indem der aktuelle Farbwert der Schaltfläche mit Ihrem Farbwert multipliziert wird. Ich bin sicher, dass Sie mit diesen Modi noch viel mehr tun können.


2
Wow, habe das gerade ausprobiert und es ist total fantastisch. Vielen Dank! Wissen Sie zufällig, ob es eine Möglichkeit gibt, dies irgendwie über XML zu erreichen?
Emmby

4
Leute, schaut es euch auf dem HTC Desire an! Sie haben verschiedene Standardtasten. Meine Schaltflächen, die diesen Code verwenden, sehen dort beeindruckend aus, wenn eine bestimmte layout_width wie "40dp" eingestellt wird. Mit "wrap_content" ist das in Ordnung.
OneWorld

5
Bestätigt, diese Lösung funktioniert nicht sehr gut auf HTC Sense UI
emmby

19
Eclipse zeigt dies nicht als mögliche Lösung:import android.graphics.PorterDuff;
Jemand irgendwo

2
Hat jemand Probleme damit gehabt, dass er nicht in ICS funktioniert? Es scheint nicht auf dem Emulator oder Telefon für mich zu funktionieren ..
Stev_k

149

Mike, vielleicht interessieren dich Farbfilter.

Ein Beispiel:

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

Versuchen Sie dies, um die gewünschte Farbe zu erzielen.


Versuchen Sie, in der setColorFilter-Methode null zu übergeben. Ich habe es nicht versucht, aber es sollte funktionieren.
Tomasz

6
@Pacerier zum Deaktivieren: button.getBackground (). ClearColorFilter ();
Stan Kurdziel

3
Ich empfehle die Auswahl einer Farbe mithilfe der Farbklasse: developer.android.com/reference/android/graphics/Color.html
Mugen

Perfekt für dunkle Themen! Ich gehe davon aus, dass die andere Top-Antwort (setColorFilter (0xFFFF0000, PorterDuff.Mode.MULTIPLY)) für leichte Themen besser funktioniert.
java.is.for.desktop

85

Dies ist meine Lösung, die ab API 15 perfekt funktioniert . Diese Lösung behält alle Standard-Schaltflächenklick-Effekte wie Material beiRippleEffect . Ich habe es nicht auf niedrigeren APIs getestet, aber es sollte funktionieren.

Alles was Sie tun müssen, ist:

1) Erstellen Sie einen Stil, der sich nur ändert colorAccent:

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

Ich empfehle, ThemeOverlay.AppCompatoder Ihr Haupt AppThemeals Elternteil zu verwenden, um den Rest Ihrer Stile beizubehalten.

2) Fügen Sie Ihrem buttonWidget diese beiden Zeilen hinzu :

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

Manchmal wird Ihr neues colorAccentGerät nicht in der Android Studio-Vorschau angezeigt, aber wenn Sie Ihre App auf dem Telefon starten, wird die Farbe geändert.


Beispiel-Button-Widget

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

Beispielknopf mit benutzerdefinierter Farbe


1
Was macht diese Linie? "style =" @ style / Widget.AppCompat.Button.Colored ""
Charles Li

2
Dies half mir, den Unterschied zwischen Stil und Thema zu verstehen. Vielen Dank.
Rpattabi

2
Akzeptierte Antwort ist richtig, aber zu alt. Diese Antwort ist einfach und auf dem neuesten Stand.
白 布鞋

Das Problem bei dieser Antwort ist, dass die Einstellung colorAccentmehr als nur den Hintergrund der Schaltfläche beeinflusst.
Blcknx

@Blcknx Was zum Beispiel?
RediOne1

61

Sie können nun auch AppCompat-v7 der Verwendung AppCompatButton mit dem backgroundTintAttribute:

<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
Hat bei mir mit dem Namespace "android:" nicht funktioniert. Aber es hat funktioniert, als ich stattdessen den Namespace "app:" verwendet habe.
David Velasquez

@ DavidVelasquez Das hat auch bei Android Lollipop funktioniert, während Android: Namespace nichts geändert hat. Danke für die Hilfe!
Avinash Prabhakar

Dies ist die einfachste Lösung und sollte die akzeptierte Antwort sein. Mit Android: backgroundTint funktioniert für mich.
Ramashish Baranwal

1
Muss app:backgroundTintstatt android:backgroundTintbei Verwendung von AppCompat sein.
Hafez Divandari

23

Ich mag den Farbfiltervorschlag in früheren Antworten von @conjugatedirection und @Tomasz; Ich stellte jedoch fest, dass der bisher bereitgestellte Code nicht so einfach anzuwenden war, wie ich erwartet hatte.

Zunächst wurde nicht erwähnt, wo der Farbfilter angewendet und gelöscht werden soll. Es ist möglich, dass es andere gute Orte gibt, um dies zu tun, aber mir fiel ein OnTouchListener ein .

Nach meiner Lektüre der ursprünglichen Frage wäre die ideale Lösung eine, die keine Bilder enthält. Die akzeptierte Antwort mit custom_button.xml von @emmby passt wahrscheinlich besser als Farbfilter, wenn dies Ihr Ziel ist. In meinem Fall beginne ich mit einem PNG-Bild eines UI-Designers, das zeigt, wie die Schaltfläche aussehen soll. Wenn ich den Hintergrund der Schaltfläche auf dieses Bild einstelle, geht das Standard-Feedback zur Hervorhebung vollständig verloren. Dieser Code ersetzt dieses Verhalten durch einen programmatischen Verdunkelungseffekt.

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

Ich habe dies als separate Klasse für die Anwendung auf mehrere Schaltflächen extrahiert - als anonyme innere Klasse angezeigt, um die Idee zu bekommen.


Das war eine großartige Lösung! Meistens der gleiche
Effekt

Ich habe dies mit 2 Tasten auf dem gleichen Bildschirm mit dem gleichen Hintergrund versucht und der Effekt gilt für beide Tasten auf Touch
Goofy

16

Wenn Sie Farbschaltflächen mit XML erstellen, können Sie den Code etwas übersichtlicher gestalten, indem Sie den fokussierten und gedrückten Status in einer separaten Datei angeben und wiederverwenden. Mein grüner Knopf sieht so aus:

<?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
nett. Wie könnte man den fokussierten und gedrückten Zustand dazu bringen, auf Standard-Android-Definitionen für Schaltflächen zurückzugreifen?
Larham1

Ich bin mir ziemlich sicher, dass Sie dies nicht tun, da die Standard-Android-Schaltflächen als 9-Patch-Bitmaps implementiert sind.
haemish

12

Die kürzeste Lösung, die mit jeder Android-Version funktioniert:

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

Anmerkungen / Anforderungen :

  • Verwenden Sie den app:Namespace und nicht denandroid: Namespace!
  • Appcompat-Version> 24.2.0

    Abhängigkeiten {compile 'com.android.support:appcompat-v7:25.3.1'}

Erklärung : Geben Sie hier die Bildbeschreibung ein


1
Interessanterweise hat bei mir app:backgroundTint="@color/my_color"nicht funktioniert. android:backgroundTint="@color/my_color"hat aber perfekt funktioniert.
Igor

Dies ist die kürzeste und sauberste Lösung für mich und das ist alles.
Marty

11

Ich benutze diesen Ansatz

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>

Wie Sie oben sehen können, verwende ich einen benutzerdefinierten Stil für meine Schaltfläche. Die Tastenfarbe entspricht der Akzentfarbe. Ich finde dies ein viel besserer Ansatz als das Einstellen, android:backgroundda ich den von Google bereitgestellten Welleneffekt nicht verliere.


8

Es gibt jetzt einen viel einfacheren Weg: android-holo-colors.com

Damit können Sie die Farben aller Holo-Zeichen (Knöpfe, Spinner, ...) einfach ändern. Sie wählen die Farbe aus und laden dann eine Zip-Datei mit Zeichen für alle Auflösungen herunter.


8

Verwenden Sie es auf diese Weise:

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

4

In <Button>Gebrauch android:background="#33b5e5". oder besserandroid:background="@color/navig_button"


3

Die DroidUX- Komponentenbibliothek verfügt über ein ColorButtonWidget, dessen Farbe sowohl über die XML-Definition als auch programmgesteuert zur Laufzeit leicht geändert werden kann, sodass Sie dem Benutzer sogar erlauben können, die Farbe / das Thema der Schaltfläche festzulegen, wenn Ihre App dies zulässt.



2

Sie können das Thema Ihrer Schaltfläche darauf einstellen

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

1

Eine einfache Möglichkeit besteht darin, einfach eine benutzerdefinierte Button-Klasse zu definieren, die alle gewünschten Eigenschaften wie Radius, Verlauf, gepresste Farbe, normale Farbe usw. akzeptiert und diese dann einfach in Ihren XML-Layouts verwendet, anstatt den Hintergrund mithilfe von XML einzurichten. Ein Beispiel ist hier

Dies ist äußerst nützlich, wenn Sie viele Schaltflächen mit denselben Eigenschaften wie Radius, ausgewählte Farbe usw. haben. Sie können Ihre geerbte Schaltfläche anpassen, um diese zusätzlichen Eigenschaften zu verarbeiten.

Ergebnis (Es wurde kein Hintergrundwähler verwendet).

Normaler Knopf

Normales Bild

Taste gedrückt

Geben Sie hier die Bildbeschreibung ein


0

Die Art und Weise, wie ich eine andere gestaltete Schaltfläche mache, die recht gut funktioniert, besteht darin, das Schaltflächenobjekt zu unterordnen und einen Farbfilter anzuwenden. Dies behandelt auch aktivierte und deaktivierte Zustände, indem ein Alpha auf die Schaltfläche angewendet wird.

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

values ​​\ 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>

dann:

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

Ergebnis


0

Gemäß den Richtlinien für das Materialdesign müssen Sie den folgenden Stil verwenden

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

und fügen Sie im Layout diese Eigenschaft Ihrer Schaltfläche hinzu

    android:theme="@style/MyButton"

0

Es ist einfach. Fügen Sie diese Abhängigkeit in Ihr Projekt ein und erstellen Sie eine Schaltfläche mit 1. Beliebiger Form 2. Beliebiger Farbe 3. Beliebiger Rand 4. Mit Materialeffekten

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" />
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.