Lollipop'un arka planı Tint'in bir Düğme üzerinde etkisi yoktur


83

Aktivitemde bir Düğme var ve temamın vurgu rengine sahip olmasını istiyorum. Lollipop öncesi yapmak zorunda olduğumuz gibi kendi çekilebilir öğelerimi yapmak yerine, doğal olarak yeni backgroundTintözelliği kullanmak istiyorum .

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

Maalesef bir etkisi yok, düğme gri kalıyor.

Hiçbir backgroundTintModeşeyi değiştirmeyen farklı değerler denedim .

Ayrıca bunu Aktivitemde programlı olarak yapmayı denedim, bu hiçbir şeyi değiştirmedi.

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

Renk tonum neden göz ardı ediliyor?

DÜZENLEME: Sadece açıklığa kavuşturmak için, gerçekten bir Lollipop cihazı üzerinde test ediyorum. Diğer widget'lar (örneğin EditText) doğru ve otomatik olarak renklendirilir.


3
Bu, gelecekteki bir sürüm için düzeltilen bir hatadır, ancak kabul edilen çözüm API 21+ üzerinde çalışacaktır.
alanv

Yanıtlar:


18

API 19'da API 27 aracılığıyla test edildi

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

çıktı olarak -

görüntü açıklamasını buraya girin


Bunu kabul edilen cevap olarak işaretlemek, çünkü birkaç yıldan sonra, şu anda bunu yapmanın resmi (ve en iyi) yolu olduğuna inanıyorum. (Küçük ayrıntı: Çoğu durumda AppCompatButton yerine Button'ı kullanabileceğinizden oldukça eminim ve yine de çalışacaktır).
YK

118

Kötü haber

BoD'nin dediği gibi, bir Button'ın arka planını Lollipop 5.0'da (API seviyesi 21) renklendirmek anlamsız.

Güzel haberler

Lollipop 5.1 (API seviyesi 22), btn_mtrl_default_shape.xml'yi (diğer dosyaların yanı sıra) değiştirerek bunu çözmüş görünüyor: https://android.googlesource.com/platform/frameworks/base/+/6dfa60f33ca6018959ebff1efde82db7d2aed1e3%5E!/#F0

Harika haber

Yeni destek kitaplığı (sürüm 22.1+) geriye dönük olarak uyumlu renklendirme destek ekler dahil bileşenlerin, bir sürü AppCompatButton !

Ne yazık ki, android:backgroundTintözellik hala çalışmıyor (belki yanlış bir şey yapıyorum) - bu yüzden ColorStateListkullanarak kodu girmeniz gerekiyor setSupportBackgroundTintList(). android:backgroundTintGelecekte desteklendiğini görmek gerçekten güzel olurdu . Güncelleme : Marcio Granzotto, bunun AppCompatButton'da app:backgroundTintçalıştığını söyledi ! Bunun , uygulama / kitaplıkta olduğu için app:olmadığını unutmayın 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>

Etkinliğiniz, miras almasına izin verirseniz AppCompatButtonnormal yerine bir otomatik olarak şişer .ButtonAppCompatActivity

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

Tabii ki ColorStateListbir renk kaynağından almalısın , ama tembelim, yani ...

Oh, ve uygulama temanızı Theme.AppCompattemalardan birine dayandırmayı unutmayın , aksi takdirde uyumluluk görünümleri çok, çok üzücü olacaktır ...;)

Bu, hem 2.3.7 (Gingerbread MR1) hem de 5.0 (Lollipop 'Classic') üzerinde çalıştı.


1
Biraz daha bilgi ekledim - en önemlisi, geçen gün yayınlanan destek kitaplığının yeni sürümü (22.1) ile artık düğme renklendirme elde etmek mümkün!
Snild Dolkow

8
colorButtonNormalAppCompat 22.1.1 ile kullanabilirsiniz (temayı yalnızca düğmeler için ayarlayarak), 4.4.4 ve 5.1'de benim için çalışıyor.
hunyadym

2
TextView için aynı şeyi nasıl ayarlayacağınıza dair bir fikriniz var mı?
android geliştiricisi

8
new ColorStateList(new int[][]{new int[0]}, new int[]{0xffffcc00});Senin yerine daha kısaca yazabilirsin ColorStateList.valueOf(0xffffcc00);.
Ashkan Sarlak


30

Görünüşe göre bir dalgalanma çekilebilirinin renklendirilmesi anlamsızdır (ve bir düğmenin varsayılan arka planı bir dalgalanma çekilebilir).

Aslında, platformun varsayılan çekilebilir düğmesine baktıktan sonra, bunu yapmanın "doğru" yolunu buldum :. Bunu temanızda tanımlamalısınız:

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

(Elbette bu sadece 21+ seviye içindir.)

Uyarı: Bu bir temada tanımlandığından, bu, tüm düğmeler için verilen rengi kullanacaktır (en azından bu temayı kullanan etkinliklerdeki tüm düğmeler).

Bonus olarak, bunu tanımlayarak dalgalanma rengini de değiştirebilirsiniz:

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

colorControlHighlightdiğer birçok widget'ı değiştirebilir. Bunu çözmene sevindim.
natario

5
Bunu, bir bindirme teması tanımlayarak (ör. Ana tema yok ve yalnızca bir öznitelik tanımlı) ve android: theme özelliğini kullanarak bireysel bir görünüme uygulayabilirsiniz.
alanv

1
O halde API 22 ve üstü için nasıl düzeltildi? Ayrıca bu "hata" yalnızca API 21'in bazı cihazlarında (bağlantı
noktası

22

Android 5.0.x'te renklendirme ile ilgili sorunları çözmek için şuna benzer bir şey kullanıyorum:

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

Destek yöntemini yalnızca API 21 için ve diğer tüm durumlar için ViewCompat birini kullanır.


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

Bu, lolipop öncesi cihazlarda bir ImageButton ile çalışmaz.
toobsco42

AppCompatButton.setSupportBackgroundTintList () AppCompatButton.setSupportBackgroundTintList'i kullanırken yalnızca aynı kütüphane grubundan çağrılabilir (groupId = com.android.support)
starkej2

Benim için işe yaradı ama koşulları tersine çevirmek zorunda kaldım.
Rodrigo Venancio

"yalnızca aynı kitaplık grubundan çağrılabilir (groupId = com.android.support" neden bu uyarı?
Ferran Negre

22

Bunu genellikle PorterDuff kullanarak dinamik olarak yapıyorum:

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

Farklı karıştırma modlarını kontrol edebilirsiniz burada ve güzel örnekler burada .


1
PorterDuff.Mode.SRC'yi kullandım ve mükemmel çalışıyor
francisco_ssb

Mükemmel çalışıyor. Benim durumumda API 17'de renklendirme efekti kullanmak istedim, bu bana yardımcı oldu.
ashishdhiman2007

2
Kabul edilen cevap bu olmalıdır. API 20 üzerinde çalışmayı onaylayın.
hardanger

19

Bunun app:backgroundTintyerine kullanın android:backgroundTint, renk Lollipop'un altında etkili olacaktır. Nedeni AppCompatActivityKullanım AppCompatViewInflaterAppCompatButton veya AppCompatTextView için otomatik değiştirme Button veya TextView, sonra app:backgroundTintyürürlüğe girecek.

görüntü açıklamasını buraya girin

Projemde kullandım, işe yaradı.


9

Sana olması gerektiğini düşünüyorum android:backgroundbırakmak üzere yola android:backgroundTintişi.

Daha doğru olmak gerekirse, benim tahminim, backgroundTinta olarak tanımlanan Malzeme temalarından varsayılan düğme arka planını yapamazsınız RippleDrawable.


1
Bence haklısın Aslında istediğim şeyi yapmanın "doğru" yolunu buldum (cevabıma bakın).
BoD

3

Google https://code.google.com/p/android/issues/detail?id=201873 adresinde benzer bir sorun bildirildi

Ancak Android Destek Kitaplığı'nın yayımlanmasından sonra, revizyon 23.2.1 (Mart 2016) Bu hata çözüldü.

Sorun: FloatingActionButton.setBackgroundTintList (@Nullable ColorStateList renk tonu) artık arka plan rengini değiştirmiyor

Destek Kitaplığını güncelle Android Support Library to 23.2.1

Kullanım tasarım destek kitaplığı (23.2.1) ve appcompatwidgets aşağıdaki gibi

Lolipop Öncesi Cihazlar için Materyal Tasarımı :

AppCompat (diğer adıyla ActionBarCompat), Gingerbread üzerinde çalışan cihazlar için Android 4.0 ActionBar API'nin bir arka portu olarak başladı ve arkaya yerleştirilen uygulama ve çerçeve uygulaması üzerine ortak bir API katmanı sağladı. AppCompat v21, Android 5.0 ile güncel bir API ve özellik seti sunar


Android Destek Kitaplığı 22.1 :

AppCompat kullanırken widget'ları otomatik olarak renklendirme yeteneği, uygulamanızda güçlü bir marka bilinci oluşturma ve tutarlılık sağlamada inanılmaz derecede yararlıdır. Bu, düzenleri şişirirken otomatik olarak yapılır - her birinin renklendirmeyi desteklediğinden emin olmak için Button yerine AppCompatButton, TextView ile AppCompatTextView vb. Bu sürümde, bu renk tonuna duyarlı pencere öğeleri artık herkesin kullanımına açık olup, desteklenen pencere öğelerinin birini alt sınıflara ayırmanız gerekse bile renk tonu desteğini sürdürmenize olanak tanır.



2

Destek Kitaplığı'nın kaynak koduna bakarsak, normalde bilinen düğmeleri renklendirdiğini görürüz, ancak düğmemizin şeklini değiştirirsek (yuvarlak düğmem var) renk tonu api <= 21'de düzgün çalışmaz. Ayrıca TintManager'ın genel sınıf haline geldiğini görebiliriz (appcompat-v7: 23.1.1), böylece ColorStateList'i mevcut tema için varsayılan düğme şeklinden (5.0'da renklendirilmiş) alabiliriz (bu nedenle diziyi oluşturmak zorunda değiliz) renk sayısı):

    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'den beri sınıfı değiştirdiler (genel olsa da!) TintManager -> AppCompatDrawableManager kod hemen hemen aynı kalıyor
Pavel Biryukov

WTF ... getTintList artık genelden korumalı olarak değiştirildi; (yansımayı kullanmak gerekiyor :)
Pavel Biryukov

0

Çünkü öznitelik backgroundTintyalnızca API seviyesi 21 ve üzerinde kullanılır


Bunun farkındayım ve gerçekten bir Lollipop cihazı üzerinde test yapıyorum. Bunu netleştirmek için soruyu güncelleyeceğim.
YK

0

Recyclerview'un en güncel lib'lerinin de bu hataya neden olabileceğinin farkında olun.

Bu komut

  sendBtnView.setBackgroundTintList(colorState)

geçmişte mükemmel çalıştı ama benim için çalışmayı bırak. Araştırmadan sonra, bağımlılıkları derecelendirmeye eklenen lib'nin nedeni ortaya çıkıyor:

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

Bu yüzden Amit Vaghela yazısında önerildiği gibi onu 23.02.1 olarak değiştirmeye çalıştım. Değiştim

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

Ancak gradle hatası, recyclerview lib'nin bu sürüme (23.02.1) sahip olmadığını söyledi (gradle, Jcenter raw.github veya repo'da bulamadı).

Sonra, setBackgroundTintList komutunun, gradle bağımlılıklarında sahip olduğum diğer tüm kitaplıklarda 22.02.0 'sürümüyle iyi çalıştığını bildiğim için. bu yüzden şu şekilde değiştiriyorum:

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

Ve şimdi tekrar çalışıyor.


0

Bunun tavsiye edildiğinden emin değilim ama şunu deneyebilirsiniz:

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

Genel anlamda işe yarıyor. Denedim ViewCompatama düzgün çalışmıyor.


0

versiyonu backgroundTint <android.support.design.button.MaterialButtonile kullanabilirsiniz"com.android.support:design:28.0.0-rc01"


0

Androidx kullanıyorsanız, hem önekli hem de önekli olmayan sürümü eklemek, android 5.1'de sorunu çözdü:

<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 colorşu içeriğe sahip klasörde:

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

ve normal düğmeye uygulayın AppCompatActivity

<Button style="@style/Button_Primary"/>
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.