Nền tảng của Lollipop Gợi ý không ảnh hưởng đến Nút


82

Tôi có một Nút trong Hoạt động của mình và tôi muốn nó có màu nhấn cho chủ đề của tôi. Thay vì tạo các bảng vẽ của riêng tôi như chúng tôi đã làm trước Lollipop, tự nhiên tôi muốn sử dụng backgroundTintthuộc tính mới .

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

Thật không may, nó không có tác dụng, nút vẫn có màu xám.

Tôi đã thử các giá trị khác nhau backgroundTintMode, không thay đổi được gì.

Tôi cũng đã thử làm điều đó theo chương trình trong Hoạt động của mình, điều này không thay đổi bất cứ điều gì.

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

Tại sao màu của tôi bị bỏ qua?

CHỈNH SỬA: Chỉ để làm rõ, tôi thực sự đang thử nghiệm trên thiết bị Lollipop. Các widget khác (ví dụ: EditText) được tô màu một cách chính xác và tự động.


3
Đây là một lỗi đã được sửa cho bản phát hành trong tương lai, nhưng giải pháp được chấp nhận sẽ hoạt động trên API 21+.
alanv

Câu trả lời:


18

Đã thử nghiệm trên API 19 đến 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" />

sản xuất đầu ra là -

nhập mô tả hình ảnh ở đây


Đánh dấu đây là câu trả lời được chấp nhận vì sau vài năm, tôi tin rằng đây hiện là cách chính thức (và tốt nhất) để làm điều này. (Chi tiết nhỏ: Tôi khá chắc chắn trong hầu hết các trường hợp, bạn có thể chỉ cần sử dụng Button thay vì AppCompatButton và nó sẽ vẫn hoạt động).
BoD

116

Các tin xấu

Giống như BoD nói, việc tô màu nền của Nút trong Lollipop 5.0 (API cấp 21) là vô nghĩa.

Tin tốt

Lollipop 5.1 (API cấp 22) dường như đã khắc phục điều này bằng cách thay đổi btn_mtrl_default_shape.xml (trong số các tệp khác): https://android.googlesource.com/platform/frameworks/base/+/6dfa60f33ca6018959ebff1efde82db7d2aed1e3%5E!/#F0

Tin tuyệt vời

Thư viện hỗ trợ mới (phiên bản 22.1+) bổ sung hỗ trợ pha màu tương thích ngược cho nhiều thành phần, bao gồm cả AppCompatButton !

Thật không may, thuộc android:backgroundTinttính vẫn không hoạt động (có thể tôi đang làm sai điều gì đó) - vì vậy bạn phải đặt ColorStateListmã bằng cách sử dụng setSupportBackgroundTintList(). Sẽ rất vui nếu android:backgroundTintđược hỗ trợ trong tương lai. Cập nhật : Marcio Granzotto nhận xét rằng app:backgroundTinthoạt động trên AppCompatButton! Lưu ý rằng nó app:, không phải android:, vì nó nằm trong ứng dụng / thư viện.

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

Hoạt động của bạn sẽ tự động tăng một AppCompatButtonthay vì bình thường Buttonnếu bạn để nó kế thừa từ đó 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);
    }
}

Tất nhiên bạn nên lấy ColorStateListtừ tài nguyên màu, nhưng tôi lười, vì vậy ...

Ồ, và đừng quên đặt chủ đề ứng dụng của bạn dựa trên một trong các Theme.AppCompatchủ đề, nếu không chế độ xem tổng hợp sẽ rất, rất buồn ...;)

Điều này hoạt động trên cả 2.3.7 (Gingerbread MR1) và 5.0 (Lollipop 'Classic').


1
Chỉ cần thêm một số thông tin - quan trọng nhất, bây giờ có thể đạt được màu sắc của nút với phiên bản mới (22.1) của thư viện hỗ trợ đã được phát hành vào ngày hôm trước!
Snild Dolkow

8
Bạn có thể sử dụng colorButtonNormalvới AppCompat 22.1.1 (chỉ thiết lập chủ đề cho các nút), nó hoạt động với tôi trên 4.4.4 và 5.1.
hunyadym

2
Bất kỳ ý tưởng nào về cách thiết lập điều tương tự cho TextView?
nhà phát triển android

8
Thay vào đó new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});bạn có thể viết ngắn gọn hơn ColorStateList.valueOf(0xffffcc00);.
Ashkan Sarlak

5
Bạn có thể sử dụng android.support.v7.widget.AppCompatButton với ứng dụng: backgroundTint trên xml
Marcio Granzotto

30

Có vẻ như việc tô màu một gợn sóng có thể vẽ là vô nghĩa (và nền mặc định của nút là một gợn sóng có thể vẽ được).

Trên thực tế, sau khi nhìn vào nút mặc định có thể vẽ của nền tảng, tôi đã tìm thấy cách "chính xác" để làm điều này:. Bạn phải xác định điều này trong chủ đề của mình:

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

(Tất nhiên điều này chỉ dành cho cấp 21+.)

Cảnh báo: vì điều này được xác định trong một chủ đề, điều này sẽ sử dụng màu đã cho cho tất cả các nút (ít nhất là tất cả các nút trong các hoạt động sử dụng chủ đề đó.)

Như một phần thưởng, bạn cũng có thể thay đổi màu gợn sóng bằng cách xác định điều này:

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

colorControlHighlightsẽ thay đổi rất nhiều vật dụng khác. Rất vui vì bạn đã làm ra nó.
natario

5
Bạn có thể áp dụng điều này cho một chế độ xem riêng lẻ bằng cách xác định chủ đề lớp phủ (ví dụ: không có chủ đề mẹ và chỉ xác định một thuộc tính) và sử dụng thuộc tính android: theme.
alanv

1
Sau đó, nó được sửa như thế nào cho API 22 trở lên? Ngoài ra, "lỗi" này chỉ xảy ra trong một số thiết bị của API 21 (bao gồm nexus 5, galaxy s3)
vedant

22

Để giải quyết các vấn đề liên quan đến pha màu trên Android 5.0.x, tôi sử dụng một cái gì đó như sau:

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

Nó chỉ sử dụng phương pháp hỗ trợ cho API 21 và một trong những ViewCompat cho tất cả các trường hợp khác.


@Marco Sử dụng:if (view instanceof TintableBackgroundView) { ((TintableBackgroundView) view).setSupportBackgroundTintList(tint); } else { ViewCompat.setBackgroundTintList(view, tint); }
flagsdork

Điều này không hoạt động với ImageButton trên các thiết bị tiền kẹo mút.
toobsco42

Tôi nhận được một cảnh báo khi sử dụng lint AppCompatButton.setSupportBackgroundTintList () AppCompatButton.setSupportBackgroundTintList chỉ có thể được gọi từ bên trong nhóm cùng một thư viện (groupId = com.android.support)
starkej2

Nó hiệu quả với tôi nhưng tôi phải đảo ngược các điều kiện.
Rodrigo Venancio

"chỉ có thể được gọi từ bên trong nhóm cùng một thư viện (groupId = com.android.support" tại sao cảnh báo này?
Ferran Negre

22

Tôi thường làm điều đó động bằng cách sử dụng PorterDuff:

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

Bạn có thể kiểm tra các chế độ hòa trộn khác nhau ở đây và các ví dụ đẹp ở đây .


1
Tôi đã sử dụng PorterDuff.Mode.SRC và nó hoạt động hoàn hảo
francisco_ssb

Hoạt động hoàn hảo. Trong trường hợp của tôi, tôi muốn sử dụng hiệu ứng pha màu trên API 17, điều này đã giúp tôi.
ashishdhiman2007 Ngày

2
Đây phải là câu trả lời được chấp nhận. Xác nhận đang hoạt động trên API 20.
hardanger 27/02


9

Tôi nghĩ bạn cần phải chuẩn bị android:backgroundđể làm android:backgroundTintviệc.

Để chính xác hơn, tôi đoán là bạn không thể backgroundTintlàm nền nút mặc định từ chủ đề Material, được định nghĩa là a RippleDrawable.


1
Tôi nghĩ rằng bạn là chính xác. Trên thực tế, tôi đã tìm ra cách "chính xác" để làm những gì tôi muốn (xem câu trả lời của tôi).
BoD

3

Sự cố tương tự đã được báo cáo trên google https://code.google.com/p/android/issues/detail?id=201873

Nhưng sau khi phát hành Thư viện hỗ trợ Android, bản sửa đổi 23.2.1 (tháng 3 năm 2016), lỗi này đã được giải quyết.

Sự cố: FloatingActionButton.setBackgroundTintList (@Nullable ColorStateList tint) không còn thay đổi màu nền

cập nhật Thư viện hỗ trợ thành Android Support Library to 23.2.1

Sử dụng thư viện hỗ trợ thiết kế (23.2.1)appcompatwidgets như bên dưới

Material Design cho các thiết bị Pre-Lollipop :

AppCompat (hay còn gọi là ActionBarCompat) bắt đầu như là một nền tảng của API Android 4.0 ActionBar dành cho các thiết bị chạy trên Gingerbread, cung cấp một lớp API chung trên đầu việc triển khai backported và triển khai khung. AppCompat v21 cung cấp một API và bộ tính năng được cập nhật với Android 5.0


Thư viện hỗ trợ Android 22.1 :

Khả năng tự động tô màu các widget khi sử dụng AppCompat vô cùng hữu ích trong việc duy trì tính nhất quán và thương hiệu mạnh mẽ trong toàn bộ ứng dụng của bạn. Điều này được thực hiện tự động khi thổi phồng bố cục - thay thế Nút bằng AppCompatButton, TextView bằng AppCompatTextView, v.v. để đảm bảo rằng mỗi bố cục có thể hỗ trợ pha màu. Trong bản phát hành này, các tiện ích nhận biết màu sắc đó hiện đã được công bố công khai, cho phép bạn tiếp tục hỗ trợ màu sắc ngay cả khi bạn cần phân loại một trong các tiện ích con được hỗ trợ.


3

Chỉ cần sử dụng ứng dụng: backgroundTint thay vì android: backgroundTint


2

Nếu chúng ta xem xét mã nguồn của Thư viện hỗ trợ, chúng ta thấy rằng nó có màu bình thường là các nút đã biết, nhưng nếu chúng ta thay đổi hình dạng của nút (tôi có nút tròn) thì màu không hoạt động tốt trong api <= 21. Chúng ta cũng có thể thấy rằng TintManager đã trở thành lớp công khai (appcompat-v7: 23.1.1), vì vậy chúng ta có thể lấy ColorStateList từ hình dạng nút mặc định (được tô màu ổn trong 5.0) cho chủ đề hiện tại (vì vậy chúng ta không phải tạo mảng màu sắc):

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

kể từ appcompat 23,2 họ đã thay đổi lớp (mặc dù công của nó!) TintManager -> AppCompatDrawableManager mã ở lại gần như giống nhau
Pavel Biryukov

WTF ... getTintList thay đổi từ công chúng để bảo vệ bây giờ; (cần phải phản ánh sử dụng :)
Pavel Biryukov

0

Vì thuộc tính backgroundTintchỉ được sử dụng trong API cấp 21 trở lên


Tôi nhận ra điều đó và tôi thực sự đang thử nghiệm trên thiết bị Lollipop. Tôi sẽ cập nhật câu hỏi để làm rõ điều này.
BoD

0

Hãy lưu ý rằng bản tái chế hầu hết các bản cập nhật lib cũng có thể gây ra lỗi này.

Lệnh này

  sendBtnView.setBackgroundTintList(colorState)

hoạt động hoàn hảo trong quá khứ nhưng ngừng hoạt động đối với tôi. Sau khi nghiên cứu, nó chỉ ra nguyên nhân là do lib đã được thêm vào phụ thuộc gradle:

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

Vì vậy, tôi đã cố gắng thay đổi nó thành 23.02.1 như nó đã được đề xuất ở đây trong bài đăng của Amit Vaghela. Tôi đã đổi thành

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

Nhưng lỗi gradle nói rằng lib render không có phiên bản này (23.02.1) (không thể tìm thấy gradle trong Jcenter raw.github hoặc repo).

Sau đó, vì tôi biết lệnh setBackgroundTintList được sử dụng để giải thích tốt trong quá khứ với phiên bản 22.02.0 'trong tất cả các lib khác mà tôi có trong phụ thuộc gradle. vì vậy tôi thay đổi nó thành:

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

Và bây giờ nó hoạt động trở lại.


0

Tôi không chắc liệu điều này có được khuyến nghị hay không nhưng bạn có thể thử:

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

Theo nghĩa chung, nó hoạt động. Đã thử ViewCompatnhưng có vẻ như nó không hoạt động bình thường.


0

bạn có thể sử dụng backgroundTint <android.support.design.button.MaterialButtonvới "com.android.support:design:28.0.0-rc01"phiên bản


0

Nếu bạn đang sử dụng androidx thì việc thêm cả phiên bản có tiền tố và không có tiền tố đã giải quyết vấn đề trên 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 selector nằm trong colorthư mục có nội dung sau:

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

và áp dụng nó trên nút thông thường trên AppCompatActivity

<Button style="@style/Button_Primary"/>
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.