Фон льодяника відтінок не впливає на кнопку


83

У моїй діяльності є кнопка, і я хотів би, щоб вона мала колір акценту моєї теми. Замість того, щоб робити свої власні малюнки, як це нам потрібно було робити до льодяника, я, природно, хотів би використати новий backgroundTintатрибут.

<Button
    android:id="@+id/btnAddCode"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:backgroundTint="@color/accent"
    android:text="@string/addressInfo_edit_addCode" />

На жаль, це не спрацьовує, кнопка залишається сірою.

Я спробував різні значення backgroundTintMode, які нічого не змінили.

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

addCodeView.findViewById(R.id.btnAddCode).setBackgroundTintList(
     getResources().getColorStateList(R.color.accent));

Чому мій відтінок ігнорується?

EDIT: Тільки для уточнення, я справді тестую на пристрої Lollipop. Інші віджети (наприклад, EditText) правильно та автоматично підфарбовуються.


3
Ця помилка виправлена ​​для майбутнього випуску, але прийняте рішення буде працювати на API 21+.
alanv

Відповіді:


18

Випробувано на API 19 через API 27

<?xml version="1.0" encoding="utf-8"?>
  <android.support.v7.widget.AppCompatButton 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    style="@style/Widget.AppCompat.Button.Colored"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="@string/retry"
    android:textColor="@android:color/white"
    app:backgroundTint="@android:color/holo_red_dark" />

виробляє продукцію як -

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


Позначивши це як прийняту відповідь, тому що через кілька років я вважаю, що зараз це офіційний (і найкращий) спосіб зробити це. (Незначні деталі: Я майже впевнений, що в більшості випадків ви можете просто використовувати Button замість AppCompatButton, і це все одно буде працювати).
BoD

118

Погані новини

Як каже BoD, безглуздо тонувати фон кнопки в Lollipop 5.0 (рівень API 21).

Хороша новина

Lollipop 5.1 (рівень API 22), схоже, виправив це, змінивши btn_mtrl_default_shape.xml (серед інших файлів): https://android.googlesource.com/platform/frameworks/base/+/6dfa60f33ca6018959ebff1efde82db7d2aed1e3%5E0F5

Чудова новина

Нова бібліотека підтримки (версія 22.1+) додає зворотну сумісну підтримку тонування для багатьох компонентів, включаючи AppCompatButton !

На жаль, android:backgroundTintвластивість все ще не працює (можливо, я роблю щось не так) - тому вам доведеться встановити ColorStateListкод in, використовуючи setSupportBackgroundTintList(). Було б дуже приємно бачити android:backgroundTintпідтримку в майбутньому. Оновлення : Марсіо Гранзотто прокоментував, що app:backgroundTintпрацює на AppCompatButton! Зверніть увагу, що це app:ні android:, тому що це в додатку / бібліотеці.

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <AppCompatButton
        android:id="@+id/mybutton"
        android:layout_width="wrap_content" android:layout_height="wrap_content"
        android:text="Testing, testing"
        app:backgroundTint="#ff00ff"/>

</LinearLayout>

Ваша активність автоматично роздується AppCompatButtonзамість звичайної, Buttonякщо ви дозволите їй успадковувати від AppCompatActivity.

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        AppCompatButton v = (AppCompatButton) findViewById(R.id.mybutton);
        ColorStateList csl = new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});
        v.setSupportBackgroundTintList(csl);
    }
}

Звичайно, вам слід отримати ColorStateListз кольорового ресурсу, але я лінувався, тому ...

О, і не забувайте базувати тему програми на одній з Theme.AppCompatтем, інакше погляди порівняння будуть дуже, дуже сумними ...;)

Це працювало як на версії 2.3.7 (Gingerbread MR1), так і на 5.0 (Lollipop 'Classic').


1
Просто додав трохи більше інформації - головне, тепер можна досягти тонування кнопок за допомогою нової версії (22.1) бібліотеки підтримки, яка вийшла днями!
Snild Dolkow

8
Ви можете використовувати colorButtonNormalз AppCompat 22.1.1 (встановлення теми лише для кнопок), це працює для мене на 4.4.4 та 5.1.
hunyadym

2
Будь-яка ідея, як встановити те саме для TextView?
розробник android

8
Замість цього new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});ви можете писати коротше ColorStateList.valueOf(0xffffcc00);.
Ashkan Sarlak

5
Ви можете використовувати android.support.v7.widget.AppCompatButton з app: backgroundTint на xml
Marcio Granzotto

30

Здається, що тонування пульсацій, які можна малювати, безглуздо (а фон кнопки за замовчуванням - пульсація, що малюється).

Насправді, подивившись на кнопку за замовчуванням платформи, яку можна намалювати, я знайшов "правильний" спосіб зробити це :. Ви повинні визначити це у своїй темі:

    <item name="android:colorButtonNormal">@color/accent</item>

(Звичайно, це стосується лише рівня 21+.)

Попередження: оскільки це визначено в темі, для цього буде використаний заданий колір для всіх кнопок (принаймні для всіх кнопок у заходах, що використовують цю тему.)

В якості бонусу ви також можете змінити колір пульсацій, визначивши це:

    <item name="android:colorControlHighlight">@color/accent_ripple</item>

colorControlHighlightзмінило б багато інших віджетів. Радий, що ви це розробили.
Натаріо

5
Ви можете застосувати це до індивідуального подання, визначивши накладену тему (наприклад, не встановлено батьківську тему та лише один атрибут) та використовуючи атрибут android: theme.
alanv

1
Тоді як це виправлено для API 22 і вище? Також ця "помилка" трапляється лише в деяких пристроях API 21 (включаючи nexus 5, galaxy s3)
опубліковано

22

Для вирішення проблем, пов’язаних з тонуванням на Android 5.0.x, я використовую щось подібне:

public static void setButtonTint(Button button, ColorStateList tint) {
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP && button instanceof AppCompatButton) {
        ((AppCompatButton) button).setSupportBackgroundTintList(tint);
    } else {
        ViewCompat.setBackgroundTintList(button, tint);
    }
}

Він використовує метод підтримки лише для API 21, а ViewCompat - для всіх інших випадків.


@Marco Use:if (view instanceof TintableBackgroundView) { ((TintableBackgroundView) view).setSupportBackgroundTintList(tint); } else { ViewCompat.setBackgroundTintList(view, tint); }
chessdork

Це не працює з кнопкою ImageButton на пристроях для попереднього льодяника.
toobsco42

Я отримую попередження про ворсинки при використанні AppCompatButton.setSupportBackgroundTintList () AppCompatButton.setSupportBackgroundTintList можна викликати лише з тієї ж групи бібліотек (groupId = com.android.support)
starkej2,

Це спрацювало для мене, але мені довелося змінити умови.
Родріго Венансіо

"можна викликати лише з тієї самої групи бібліотек (groupId = com.android.support", чому це попередження?
Ферран Негре

22

Зазвичай я роблю це динамічно, використовуючи PorterDuff:

mbutton = (Button) findViewById(R.id.mybutton);
mbutton.getBackground().setColorFilter(anycolor, PorterDuff.Mode.MULTIPLY);

Ви можете перевірити різні режими змішування тут, а приємні приклади тут .


1
Я використовував PorterDuff.Mode.SRC, і він чудово працює
francisco_ssb

Працює ідеально. У моєму випадку я хотів застосувати ефект тонування на API 17, це мені допомогло.
ashishdhiman2007

2
Це має бути прийнятою відповіддю. Підтвердьте роботу над API 20.
hardanger

19

Просто використовуйте app:backgroundTintзамість android:backgroundTint, відтінок набуде чинності нижче льодяника. Причиною є AppCompatActivityвикористання AppCompatViewInflaterдля автоматичного зміни Button або TextView на AppCompatButton або AppCompatTextView, а потім app:backgroundTintнабирає чинності.

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

У своєму проекті я його використовував, він спрацював.


9

Я думаю, вам потрібно було android:backgroundналаштуватися на android:backgroundTintроботу.

Щоб бути точнішим, я припускаю, що ви не можете backgroundTintза замовчуванням використовувати кнопку кнопок за темами "Матеріал", яка визначається як RippleDrawable.


1
Думаю, ти маєш рацію. Насправді я знайшов "правильний" спосіб робити те, що хочу (див. Мою відповідь).
BoD 02

3

Подібна проблема була зареєстрована на google https://code.google.com/p/android/issues/detail?id=201873

Але після випуску бібліотеки підтримки Android, версія 23.2.1 (березень 2016 р.) Ця помилка вирішена.

Проблема: FloatingActionButton.setBackgroundTintList (відтінок @Nullable ColorStateList) більше не змінює колір фону

оновити бібліотеку підтримки до Android Support Library to 23.2.1

Використовуйте бібліотеку підтримки дизайну (23.2.1) та віджети appcompat, як показано нижче

Дизайн матеріалу для пристроїв перед льодяником :

AppCompat (він же ActionBarCompat) почав свою роботу як бекпорт API Android 4.0 ActionBar для пристроїв, що працюють на Gingerbread, забезпечуючи загальний рівень API поверх реалізації, що підтримується, і реалізації фреймворку. AppCompat v21 пропонує API та набір функцій, які є сучасними для Android 5.0


Бібліотека підтримки Android 22.1 :

Можливість автоматичного підфарбовування віджетів під час використання AppCompat надзвичайно корисна для збереження чіткого брендингу та послідовності у всьому додатку. Це робиться автоматично при роздутті макетів - замінюючи Button на AppCompatButton, TextView на AppCompatTextView тощо, щоб гарантувати, що кожен з них може підтримувати тонування. У цьому випуску ці віджети, що знають про відтінки, тепер є загальнодоступними, що дозволяє вам продовжувати підтримувати тонування, навіть якщо вам потрібно підкласувати один із підтримуваних віджетів.



2

Якщо ми заглянемо у вихідний код бібліотеки підтримки, то побачимо, що він зазвичай підфарбовується - це відомі кнопки, але якщо ми змінимо форму нашої кнопки (у мене кругла кнопка), відтінок не працює нормально в api <= 21. Ми також можемо побачити, що TintManager став загальнодоступним класом (appcompat-v7: 23.1.1), тому ми можемо взяти ColorStateList із форми кнопки за замовчуванням (яка підфарбована в 5,0) для поточної теми (тому нам не потрібно створювати масив кольорів):

    Context c = ...; // activity
    AppCompatButton ab = ...; // your button
    // works ok in 22+:
    if (Build.VERSION.SDK_INT <= 21) {
        // default appcompat button, that is tinted ok with current theme colors "abc_btn_default_mtrl_shape":
        // ColorStateList tint = TintManager.get(c).getTintList(R.drawable.abc_btn_default_mtrl_shape);
        // Appcompat 23.2 change:
        ColorStateList tint = AppCompatDrawableManager.get().getTintList(c, R.drawable.abc_btn_default_mtrl_shape);
        ab.setSupportBackgroundTintList(tint);
        }

з моменту appcompat 23.2 вони змінили клас (хоч і загальнодоступний!) TintManager -> AppCompatDrawableManager код залишається майже незмінним
Павло Бірюков

WTF ... getTintList змінено з загальнодоступного на захищений зараз; (потрібно використовувати відображення :)
Павло Бірюков

0

Оскільки атрибут backgroundTintвикористовується лише в API рівня 21 і вище


Я це усвідомлюю і справді тестую на пристрої льодяник. Я оновлю питання, щоб це було зрозуміло.
BoD 02

0

Майте на увазі, що найновіша версія lib може також спричинити цю помилку.

Ця команда

  sendBtnView.setBackgroundTintList(colorState)

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

  compile 'com.android.support:recyclerview-v7:+'

Тож я спробував змінити його на 23.02.1, як це було рекомендовано тут у дописі Аміта Вагели. Я змінився на

  compile  'com.android.support:recyclerview-v7:23.02.1'

Але у помилці gradle сказано, що у бібліотеці recyclerview немає цієї версії (23.02.1) (gradle не може знайти її в Jcenter raw.github або repo).

Тоді, оскільки я знав, що команда setBackgroundTintList раніше добре працювала з версією 22.02.0 'у всіх інших бібліотеках, які я маю в залежностях gradle. тому я змінюю його на:

compile   'com.android.support:recyclerview-v7:22.02.0'

І зараз це знову працює.


0

Я не впевнений, чи рекомендується це, але ви можете спробувати це:

Drawable newDrawable = mBtnAction.getBackground();  // obtain Bg drawable from the button as a new drawable
DrawableCompat.setTint(newDrawable, mActivity.getHomeTobBarBGColor());  //set it's tint
mBtnAction.setBackground(newDrawable);  //apply back to button

У загальному сенсі це працює. Пробували, ViewCompatале, здається, це не працює належним чином.



0

Якщо ви використовуєте androidx, тоді додавання як префіксної, так і не префіксної версії вирішило проблему на Android 5.1:

<style name="Button_Primary">
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_width">wrap_content</item>
    <item name="android:backgroundTint">@color/button_primary_selector</item>
    <item name="backgroundTint">@color/button_primary_selector</item><!--needed for android 5-->
</style>

селектор button_primary знаходиться в colorпапці з таким вмістом:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android"
          xmlns:local="http://schemas.android.com/apk/res-auto">
    <item android:state_enabled="true" android:color="@android:color/holo_blue_dark" />
    <item android:state_enabled="false" android:color="@android:color/darker_gray" />
</selector>

і застосувати його до звичайної кнопки на AppCompatActivity

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