Standardowy przycisk Android z innym kolorem

Chciałbym nieco zmienić kolor standardowego przycisku Androida, aby lepiej pasował do marki klienta.

Najlepszym sposobem, jaki znalazłem, aby to zrobić, jest zmiana Button's drawable na następujące drawable znajduje się w 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>

Ale zrobienie tego wymaga stworzenia trzech różnych rysunków dla każdego przycisku, który chcę dostosować (jeden dla przycisku w spoczynku, jeden po naciśnięciu i jeden po naciśnięciu). To wydaje się bardziej skomplikowane i nie suche niż ja potrzeba.

Wszystko, co naprawdę chcę zrobić, to zastosować jakiś rodzaj transformacji koloru do przycisku. Czy istnieje łatwiejszy sposób na zmianę koloru przycisku niż ja?

Author: Catalina, 2009-10-05

18 answers

Odkryłem, że to wszystko można zrobić w jednym pliku dość łatwo. Umieść coś w rodzaju poniższego kodu w pliku o nazwie custom_button.xml, a następnie Ustaw background="@drawable/custom_button" w widoku przycisków:

<?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/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-22 12:59:16

Zgodnie z odpowiedzią Tomasza, można również programowo ustawić Odcień całego przycisku za pomocą trybu pomnożenia Porterduffa. Spowoduje to zmianę koloru przycisku, a nie tylko odcienia.

Jeśli zaczniesz od standardowego szarego przycisku cieniowanego:

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

Da ci czerwony zacieniony guzik,

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

Da ci zielony zacieniony przycisk itp., gdzie pierwszą wartością jest kolor w formacie hex.

Działa poprzez pomnożenie bieżącej wartości koloru przycisku według wartości koloru. Jestem pewien,że z tymi trybami można zrobić znacznie więcej.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-15 02:41:42

Mike, możesz być zainteresowany filtrami kolorów.

Przykład:

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

Spróbuj tego, aby uzyskać pożądany kolor.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-05 06:38:29

To jest moje rozwiązanie, które doskonale działa zaczynając od API 15. To rozwiązanie zachowuje wszystkie domyślne efekty klikania przycisków, takie jak materiał RippleEffect. Nie testowałem go na niższych interfejsach API, ale powinien działać.

Wszystko, co musisz zrobić, to:

1) Utwórz styl, który zmienia się tylko colorAccent:

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

Zalecam używanie ThemeOverlay.AppCompat lub głównego AppTheme jako rodzica, aby zachować resztę stylów.

2) Dodaj te dwie linie do swojego button widget:

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

Czasami Twój nowy colorAccent nie jest wyświetlany w Android Studio Preview, ale po uruchomieniu aplikacji na telefonie, kolor zostanie zmieniony.


Przykładowy widżet przycisku

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

Przycisk próbki z niestandardowym kolorem

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-07 05:03:14

Możesz teraz również użyć appcompat-v7 ' s AppCompatButton z atrybutem 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/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-03 05:19:45

Podoba mi się sugestia filtra kolorów w poprzednich odpowiedziach z @conjugatedirection i @Tomasz; jednak okazało się, że podany kod nie był tak łatwy do zastosowania, jak się spodziewałem.

Po pierwsze, nie wspomniano Gdzie , Aby zastosować i wyczyścić filtr kolorów. Możliwe, że są inne dobre miejsca, aby to zrobić, ale to, co przyszło mi do głowy, to OnTouchListener.

Z mojej lektury pierwotnego pytania, idealnym rozwiązaniem byłoby takie, które nie włącz dowolne obrazy. Zaakceptowana odpowiedź za pomocą custom_button.xml od @emmby jest prawdopodobnie lepiej dopasowany niż filtry kolorów, jeśli to jest twój cel. W moim przypadku zaczynam od obrazu png od projektanta interfejsu użytkownika, jak ma wyglądać przycisk. Jeśli ustawię tło przycisku na tym obrazku, domyślne sprzężenie zwrotne podświetlenia zostanie całkowicie utracone. Kod ten zastępuje to zachowanie programowym efektem zaciemnienia.

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

Wyodrębniłem to jako osobną klasę dla aplikacji do wiele przycisków-pokazane jako anonimowa Klasa wewnętrzna tylko po to, aby uzyskać pomysł.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-17 11:07:25

Jeśli tworzysz kolorowe przyciski za pomocą XML, możesz uczynić kod nieco czystszym, określając stan skupienia i naciśnięcia w osobnym pliku i ponownie je wykorzystać. Mój zielony guzik wygląda tak:

<?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/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-16 11:23:24

Najkrótsze rozwiązanie, które działa z dowolną wersją Androida:

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

Uwagi / Wymagania :

  • użyj przestrzeni nazw app: i nie przestrzeni nazw!
  • Appcompat version > 24.2.0

    Zależności { compile ' com.android.support:appcompat-v7: 25.3.1" }

Explanation : Tutaj wpisz opis obrazka

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-04 12:27:59

Używam tego podejścia

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

Jak widać z góry, używam niestandardowego stylu dla mojego przycisku. Kolor przycisku odpowiada kolorowi akcentu. Uważam to za znacznie lepsze podejście niż ustawienie android:background, ponieważ nie stracę efektu falowania, który zapewnia 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/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-05 13:23:43

Jest teraz o wiele łatwiejszy sposób: android-holo-colors.com

Pozwoli Ci zmienić kolory wszystkich Holo drawables (przyciski, Spinnery,...) łatwo. Wybierz kolor, a następnie pobierz plik zip zawierający rysunki dla wszystkich rozdzielczości.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-14 12:45:53

Użyj go w ten sposób:

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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-14 05:08:40

W <Button> użyj android:background="#33b5e5". or better 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/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-01 06:31:52

Biblioteka komponentówDroidUX posiada ColorButton widżet, którego kolor można łatwo zmienić, zarówno za pomocą definicji xml i programowo w czasie wykonywania, dzięki czemu można nawet pozwolić użytkownikowi ustawić kolor/motyw przycisku, jeśli aplikacja na to pozwala.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2011-08-05 12:53:26

Możesz również użyć tego narzędzia online, aby dostosować swój przycisk http://angrytools.com/android/button/ i użyj android:background="@drawable/custom_btn", aby zdefiniować niestandardowy przycisk w układzie.

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-27 13:09:11

Możesz ustawić motyw swojego przycisku na ten

<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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-07 10:30:57

Łatwym sposobem jest zdefiniowanie niestandardowej klasy przycisków, która akceptuje wszystkie pożądane właściwości, takie jak promień, gradient, wciśnięty Kolor, normalny kolor itp. a następnie po prostu użyj tego w swoich układach XML zamiast ustawiać tło za pomocą XML. Próbka jest tutaj

Jest to bardzo przydatne, jeśli masz wiele przycisków o takich samych właściwościach jak promień, wybrany kolor itp. Możesz dostosować odziedziczony przycisk do obsługi tych dodatkowych właściwości.

Wynik (nie użyto selektora tła).

Normalny Przycisk

Normalny Obraz

Wciśnięty Przycisk

Tutaj wpisz opis obrazka

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-13 14:13:11

Sposób, w jaki robię przycisk w innym stylu, który działa całkiem dobrze, polega na podklasowaniu obiektu przycisku i zastosowaniu filtra kolorów. To również obsługuje włączone i wyłączone Stany poprzez zastosowanie alfa do przycisku.

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/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-25 08:48:21

Wartości\style.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>

Wtedy:

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

wynik

 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/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-06 17:37:10