Стандартна кнопка Android з іншим кольором


735

Я хотів би трохи змінити колір стандартної кнопки Android, щоб краще відповідати бренду клієнта.

Найкращий спосіб, який я до цього часу знайшов, - це змінити Buttonмалюнок на той, який знаходиться в 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>

Але для цього потрібно, щоб я фактично створив три різних малюнки для кожної кнопки, яку хочу налаштувати (одну для кнопки в спокої, одну при фокусуванні та одну при натисканні). Це здається складнішим та несухим, ніж мені потрібно.

Все, що я дуже хочу зробити, це застосувати якесь перетворення кольорів на кнопку. Чи є простіший спосіб змінити колір кнопки, ніж я роблю?


Відповіді:


723

Я виявив, що це все можна зробити в одному файлі досить легко. Помістіть щось на зразок наступного коду у файлі з назвою, custom_button.xmlа потім встановіть background="@drawable/custom_button"у вашому перегляді кнопки

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

42
Це добре підходить для кольору фону - чи можна встановити колір тексту таким же чином?
Рейчел

8
Це дає мені "Error: No resource found that matches the given name (at 'color' with value '@color/yellow1')" Чи є ці посилання на вбудовані кольори? Здається, мені потрібна res / values ​​/ color.xml, щоб зробити цю роботу
Гаррі Вуд

8
@HarryWood ви повинні визначити ці кольори у вашому res / values ​​/ color.xml. Крім того, замініть їх на "# ff0000", "# 00ff00" для тестування @ cfarm54 Цей файл потрібно помістити в папку res / dravable / custom_button.xml @emmby Дякую за фрагмент коду!
espinchi

17
Чудовий вказівник, дякую! Також зверніть увагу на інших людей, які намагаються це зробити, порядок елементів у селекторі є важливим. Якщо ви поставите <item> без фільтрів стану спочатку у файлі, він перевищує решту.
mikerowehl

9
щоб зробити цю роботу, помістіть custom_button.xml у папку res / "dravable" - і створіть файл res / values ​​/ color.xml з цим вмістом: stackoverflow.com/questions/3738886/… - змініть назви кольорів у будь-якому файлі щоб він працював
самі

308

Виходячи з відповіді Томаша, ви також можете програмно встановити відтінок всієї кнопки, використовуючи режим множення PorterDuff. Це змінить колір кнопки, а не просто відтінок.

Якщо ви почнете зі стандартної сірої затіненої кнопки:

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

дасть вам червону затінену кнопку,

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

дасть вам зелену затінену кнопку тощо, де першим значенням є колір у шестигранному форматі.

Він працює, помноживши поточне значення кольору кнопки на ваше значення кольору. Я впевнений, що ви також можете зробити набагато більше з цими режимами.


2
Нічого собі, просто спробував це, і це абсолютно фантастично. Дякую! Чи знаєте ви, чи є спосіб якось виконати це через xml?
emmby

4
Хлопці, перевірте це на HTC Desire! У них різні стандартні кнопки. Мої кнопки, що використовують цей код, виглядають чудово, коли встановлюється певна ширина макета типу "40dp". З "wrap_content" це добре.
OneWorld

5
Підтверджено, що це рішення працює не дуже добре в інтерфейсі HTC Sense
emmby

19
Затьмарення не показує це як можливе виправлення:import android.graphics.PorterDuff;
Хтось десь

2
Хто-небудь мав якісь проблеми з цим не працює в ICS? Здається, це не працює на емуляторі чи телефоні для мене ..
Stev_k

149

Майку, вас можуть зацікавити кольорові фільтри.

Приклад:

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

спробуйте це, щоб досягти потрібного вам кольору.


Спробуйте передати null у методі setColorFilter. Не пробував, але це має працювати.
Томаш

6
@Pacerier для зняття: button.getBackground (). ClearColorFilter ();
Стен Курдзіель

3
Я рекомендую вибрати колір за допомогою класу Color: developer.android.com/reference/android/graphics/Color.html
Mugen

Ідеально підходить для темних тем! Я припускаю, що інша відповідь (setColorFilter (0xFFFF0000, PorterDuff.Mode.MULTIPLY)) краще працює на легкі теми.
java.is.for.desktop

85

Це моє рішення, яке чудово працює, починаючи з API 15 . Це рішення зберігає всі ефекти натискання кнопки за замовчуванням, як матеріал RippleEffect. Я не тестував його на нижчих API, але він повинен працювати.

Все, що вам потрібно зробити, це:

1) Створіть стиль, який змінюється лише colorAccent:

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

Я рекомендую використовувати ThemeOverlay.AppCompatабо ваш головний AppThemeв якості батьків, щоб зберегти решту своїх стилів.

2) Додайте ці два рядки у свій buttonвіджет:

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

Іноді ваш новий colorAccentпоказ не відображається в Android Studio Preview, але коли ви запускаєте додаток на телефоні, колір буде змінено.


Віджет кнопки віджетів

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

Кнопка зразка зі спеціальним кольором


1
Що робить ця лінія? "style =" @ style / Widget.AppCompat.Button.Colored ""
Charles Li

2
Це допомогло мені зрозуміти різницю між стилем і темою. Дякую.
рпаттабі

2
Прийнята відповідь правильна, але занадто стара. Це проста і найсучасніша відповідь.
正宗 白 布鞋

Проблема з цією відповіддю полягає в тому, що налаштування colorAccentвпливає не тільки на фон кнопки.
Blcknx

@Blcknx Що наприклад?
RediOne1

61

Тепер Ви можете також використовувати AppCompat-V7 в AppCompatButton з 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"/>

4
Не працювало для мене за допомогою простору імен "android:". Але це спрацювало, коли замість цього я застосував простір імен "app:".
Девід Веласкес

@DavidVelasquez Це працювало і для мене на Android Lollipop, а на android: простір імен нічого не змінив. Дякую за допомогу!
Авінаш Прабхакар

Це найпростіше рішення і має бути прийнятою відповіддю. Використання Android: backgroundTint працює для мене.
Рамашиш Баранваль

1
Потрібно app:backgroundTintзамість android:backgroundTintвикористання AppCompat.
Хафез Дівандарі

23

Мені подобається пропозиція щодо кольорового фільтра в попередніх відповідях від @conjugatedirection та @Tomasz; Однак я виявив, що наданий код не так легко застосований, як я очікував.

По-перше, не було зазначено, де застосувати та очистити кольоровий фільтр. Можливо, є й інші хороші місця для цього, але те, що мені прийшло в голову, було OnTouchListener .

З мого читання оригінального питання, ідеальним рішенням було б таке, що не передбачає жодних образів. Прийнята відповідь за допомогою custom_button.xml від @emmby, ймовірно, краще підходить, ніж кольорові фільтри, якщо це ваша мета. У моєму випадку я починаю з PNG зображення від дизайнера інтерфейсу користувача, як має виглядати кнопка. Якщо я встановіть фон цього зображення для цього зображення, зворотний зв'язок підсвічування за замовчуванням повністю втрачається. Цей код замінює таку поведінку ефектом програмного затемнення.

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

Я витягнув це як окремий клас для застосування до декількох кнопок - показаний як анонімний внутрішній клас, щоб отримати ідею.


Це було чудове рішення! В основному те ж саме впливає, як ви користуєтесь iOS за замовчуванням. Це те, що дизайнерам подобається :-)
Крістер Нордвік

я спробував це з 2 кнопкою на одному екрані з тим самим фоном, і ефект стосується обох кнопок onTouch
Goofy

16

Якщо ви створюєте кольорові кнопки за допомогою XML, ви можете зробити код трохи чистішим, вказавши сфокусований і натиснутий стан в окремому файлі та повторно використовувати їх. Моя зелена кнопка виглядає так:

<?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
приємно. як можна змусити зосереджений і натиснутий стан повернутися до стандартних андроїдних визначень для кнопок?
larham1

Я впевнений, що ви не використовуєте стандартні кнопки Android як 9-патч-растрові карти.
хеміш

12

Найкоротше рішення, яке працює з будь-якою версією Android:

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

Примітки / вимоги :

  • Використовуйте app:простір імен і НЕ в android:простір імен!
  • версія appcompat> 24.2.0

    залежності {compile 'com.android.support:appcompat-v7:25.3.1'}

Пояснення : введіть тут опис зображення


1
Цікаво, що для мене app:backgroundTint="@color/my_color"не вийшло. android:backgroundTint="@color/my_color"хоч працював ідеально, хоча.
Ігор

Це найкоротше і найчистіше рішення для мене, і це все.
Марті

11

Я використовую такий підхід

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>

Як ви бачите згори, я використовую власний стиль для своєї кнопки. Колір кнопки відповідає кольору акценту. Я вважаю це набагато кращим підходом, ніж налаштування, android:backgroundоскільки я не втрачу ефект пульсацій, який надає Google.


8

Зараз існує набагато простіший спосіб: android-holo-colors.com

Це дозволить вам легко змінювати кольори всіх голографічних малюнків (кнопок, прядок, ...). Ви вибираєте колір, а потім завантажуєте поштовий файл, який містить малюнки для всіх дозволів.


8

Використовуйте його таким чином:

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

4

У <Button>користуванні android:background="#33b5e5". або кращеandroid:background="@color/navig_button"


3

У бібліотеці компонентів DroidUX є ColorButtonвіджет, колір якого можна легко змінити, як за допомогою визначення xml, так і програмно під час виконання, тому ви навіть можете дозволити користувачеві встановити колір / тему кнопки, якщо програма дозволяє.


3

Ви також можете скористатися цим онлайн-інструментом для налаштування кнопки http://angrytools.com/android/button/ і використовуйте android:background="@drawable/custom_btn"для визначення спеціалізованої кнопки у своєму макеті.


2

Ви можете встановити тему своєї кнопки на це

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

1

Простий спосіб - просто визначити спеціальний клас кнопки, який приймає всі властивості, які ви хочете, як радіус, градієнт, натиснутий колір, звичайний колір тощо, а потім просто використовувати це у ваших макетах XML замість налаштування фону за допомогою XML. Зразок тут

Це надзвичайно корисно, якщо у вас є багато кнопок з такими ж властивостями, як радіус, вибраний колір тощо. Ви можете налаштувати успадковану кнопку для обробки цих додаткових властивостей.

Результат (не використовувався селектор фону).

Звичайна кнопка

Нормальне зображення

Натиснута кнопка

введіть тут опис зображення


0

Те, як я роблю іншу стильову кнопку, яка працює досить добре, - це підкласифікувати об’єкт Button та застосувати кольоровий фільтр. Це також обробляє включені та відключені стани, застосовуючи альфа-кнопку до кнопки.

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

значення \ 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>

тоді:

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

результат


0

Згідно з рекомендаціями щодо дизайну матеріалів, ви повинні використовувати стиль, як наведено нижче

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

і в макеті додайте цю властивість до вашої кнопки

    android:theme="@style/MyButton"

0

Його просто .. додайте цю залежність у свій проект і створіть кнопку з 1. Будь-яка форма 2. Будь-який колір 3. Будь-яка межа 4. З матеріальними ефектами

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" />
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.