Bir çekilebilir dosyadan stil niteliklerine nasıl başvurulur?


99

Uygulamam için 2 seçilebilir temaya sahip olmak istiyorum. Bunu yapmak için, aşağıdaki gibi bazı nitelikler tanımladım:

 <attr format="color" name="item_background" />

Sonra, şunun gibi iki temayı da oluşturdum:

  <style name="ThemeA">
     <item name="item_background">#123456</item>
 </style>

 <style name="ThemeB">
     <item name="item_background">#ABCDEF</item>
 </style>

Bu yöntem harika çalışıyor ve birkaç temayı kolayca oluşturup değiştirmeme izin veriyor. Sorun şu ki , yalnızca Görünümlerde kullanılabiliyor, Drawables'da kullanılamıyor .

Örneğin, bir mizanpajın içindeki bir View'dan bir değere başvurmak işe yarar:

 <TextView android:background="?item_background" />

Ancak aynı şeyi bir Drawable'da yapmak:

 <shape android:shape="rectangle">
     <solid android:color="?item_background" />
 </shape>

Uygulamayı çalıştırırken şu hatayı alıyorum:

    java.lang.UnsupportedOperationException: Can't convert to color: type=0x2

?item_backgroundKodlanmış bir renk kullanmak yerine işe yarıyor, ancak bu benim temalarımı kullanmama izin vermiyor. Ben de denedim ?attr:item_backgroundama aynı şey oluyor.

Bunu nasıl yapabilirim? Ve neden Görünümlerde çalışıyor ama Drawables'da çalışmıyor? Bu sınırlamayı belgelerin hiçbir yerinde bulamıyorum ...


Bu, aşağıdaki sorunun bir kopyası olabilir: stackoverflow.com/questions/7529574/…
Paul Lammertsma

@Martin M., bununla ne anladın?
user123321

Bunun için henüz bir çözüm var mı? Tam olarak aynı duvara çarpıyorum
Guillaume

Burada daha yeni bir soru daha var: stackoverflow.com/q/12115125/317889 Aynı sorun. Google'a göre sıralayın.
HGPB

3
Görünüşe göre bu sorun, burada belirtildiği gibi Android L önizlemesinde çözüldü: code.google.com/p/android/issues/detail?id=26251
Bianca Daniciuc

Yanıtlar:


167

Tecrübelerime göre, bir XML çekilebilirindeki bir niteliğe atıfta bulunmak mümkün değildir.
Temanızı oluşturmak için yapmanız gerekenler:

  • Tema başına bir XML çekilebilir oluşturun.
  • İhtiyaç duyulan rengi doğrudan @coloretiket veya #RGB formatıyla çekilebilir hale getirin.

Attrs.xml'de çekilebilir öğeniz için bir öznitelik oluşturun .

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <!-- Attributes must be lowercase as we want to use them for drawables -->
   <attr name="my_drawable" format="reference" />
</resources>

Çekilebilir dosyanızı theme.xml dosyanıza ekleyin .

<style name="MyTheme" parent="@android:style/Theme.NoTitleBar">
   <item name="my_drawable">@drawable/my_drawable</item>
</style>

Özelliğinizi kullanarak mizanpajınızda çiziminize referans verin.

<TextView android:background="?my_drawable" />

21
Görünüşe göre, uyumluluğu korumak istiyorsanız bu çözüm hala gerekli ... Evet L'den sabittir ve Tema rengine iyi referans verilir, ancak aynı kod farklı L öncesi cihazlarda çalışır ve aslında öznitelik referansı üzerinde çalışmaz. ön-L cihazlar! LoL .. Yani benim için yine de farklı çekmeceleri korumam gerekip gerekmediği sabit değil.
Davideas

2
Keşke bunu iki kez yükseltebilseydim. Sadece, sabit kodlanmış #RGB yerine referansları kullanmak için şekillerimi düzene sokmaya çalıştım ve aynı hatayı aldım. SO'ya bir çözüm için geldim ve 2 hafta önce oy kullandığım aynı cevabı buldum! (facepalm)
Tiksi

2
Bu süper ninja!
MariusBudin

4
ARGH! Bu, Google'ın backport düzeltmesi yapması için en önemli öncelik olmalıdır! ? Attr-referans gösterimi o kadar son derece yararlı ve önemlidir ki, bir uygulamada birden fazla temanız yoksa, onsuz yaşamak imkansız olmaya çok yakın. Şu anda özel düğme türlerinin her biri için üç tane çekilebilir XML yapmam gerekiyor!
Stephan Henningsen

2
İstediğim bu. <21 SDK'da çok basit ve güzel bir çözüm.
Adnan Abdollah Zaki

20

lollipop(API 21) ile başlayarak bu özellik desteklenmektedir, bkz. Https://code.google.com/p/android/issues/detail?id=26251

Bununla birlikte, lolipop içermeyen cihazları hedefliyorsanız, kilitleneceği için kullanmayın, bunun yerine kabul edilen cevaptaki geçici çözümü kullanın.


L öncesi API'ler üzerinde çalışmasını sağlamak için bir tür destek kitaplığı kullanma şansı var mı?
Ivan

2
Hayır, destek kitaplığı eski cihazlarda kullanılabilen bir dizi API'dir, bu davranış değişikliği derleyicide ve derleme araçlarında olduğu için destek kitaplığıyla ilgili değildir.
marmor

3
Hayır, lolipopta uygulanan bir özellik değil, göze batan bir hata düzeltmesiydi. Ve bunda ciddi bir hata.
Adrian Sicaru

Kahretsin, güzel bir tema çözümüm olduğunu düşündüm. şimdi geri dönüp bir sürü düğme seçici çekmecesi oluşturmam gerekiyor.
filthy_wizard

4

Lollipop öncesi cihazlarda çekilebilir öğelerden stil niteliklerine başvurmak mümkün olmasa da , renk durumu listeleri için mümkündür. Sen kullanabilirsiniz AppCompatResources.getColorStateList (Bağlam bağlamını, int Resid) Android Destek Kütüphanesi'nden yöntemi. Olumsuz yanı, bu renk durumu listelerini programlı olarak ayarlamanız gerekecek olmasıdır.

İşte çok basit bir örnek.

color / my_color_state.xml

<selector xmlns:android="http://schemas.android.com/apk/res/android">
  <item android:state_checked="true" android:color="?colorControlActivated" />
  <item android:color="?colorControlNormal" />
</selector>

Renk durumu listesine ihtiyaç duyan bir widget:

<RadioButton
  android:id="@+id/radio_button"
  android:text="My Radio" />

Ve en önemlisi:

ColorStateList csl = AppCompatResources.getColorStateList(context, R.color.my_color_state);    
RadioButton r = (RadioButton) findViewById(R.id.radio_button);
r.setTextColor(csl);

Eh, en zarif veya en kısa yol değil, ancak Android Destek Kitaplığı'nın Android'in eski sürümlerinde (Lollipop öncesi) çalışmasını sağlamak için yaptığı şey budur.

Ne yazık ki, çekilebilir öğeler için benzer yöntem stil nitelikleriyle çalışmıyor.


3

Aynı soruyu https://stackoverflow.com/a/59467269/3841352 adresinde de yanıtladım ama burada da göndereceğim:

Aynı sorunla karşılaştım ve 2019 itibariyle çözülmedi, bu nedenle bir seçicide çekilebilir olarak referans verilen bir özniteliğe sahip olamazsınız. Sorun için aldığım çözümü burada yayınladığını görmediğim için paylaşacağım. Hata raporunun son yorumunda buldum .

Geçici çözüm, temelde öznitelik değerine atıfta bulunan çekilebilir bir kaynak oluşturmaktır.

Durumunuzu açıklamak için çözüm şunun yerine olacaktır:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="?attr/colorPrimary" android:state_enabled="true" android:state_window_focused="false"/>
    <item android:drawable="?attr/colorPrimaryDark" android:state_pressed="true"/>
    <item android:drawable="@android:color/darker_gray" android:state_enabled="false"/>
    <item android:drawable="?attr/colorPrimary"/>
</selector>

çekilebilir bir kaynak için? attr / * 'yi değiştirirsiniz:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@drawable/colorPrimaryDrawable" android:state_enabled="true" android:state_window_focused="false"/>
    <item android:drawable="@drawable/colorPrimaryDarkDrawable" android:state_pressed="true"/>
    <item android:drawable="@android:color/darker_gray" android:state_enabled="false"/>
    <item android:drawable="@drawable/colorPrimaryDrawable"/>
</selector>

Çekilebilir öğeler şu şekilde tanımlanacaktır:

drawable / colorPrimaryDrawable

<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle">
    <solid android:color="?attr/colorPrimary" />
</shape>

drawable / colorPrimaryDarkDrawable

<shape xmlns:android="http://schemas.android.com/apk/res/android"android:shape="rectangle">
    <solid android:color="?attr/colorPrimaryDark" />
</shape>

Umarım yardımcı olur!!


0

@Marmor'un belirttiği gibi, bu artık API 21'de destekleniyor. Ancak Android'in eski sürümlerini desteklemesi gerekenler için bu özelliği kullanabilirsiniz. V7 destek kitaplığını kullanarak, bunu minimum SDK seviyesine sahip uygulamalarda 7'ye kadar kullanmaya devam edebilirsiniz.

AppCompatImageViewV7 Android Destek Kitaplığı bu özelliğin bir hata ücretsiz bir uygulama vardır. Basitçe sizin kullanımlarını değiştirmek ImageViewile AppCompatImageView.


2
Umut verici görünüyor! Ancak sorun, Görünüş değil Çizilebilir şekildedir. Temalı bir renk elde etmek için attr kullanan bir şekle (arka plan olarak) atıfta bulunan bir uygulama uyumlu görünümüm var ve <21'deki yukarıdaki hatayla sona eriyor. Kaçırdığım bir appcompat çekilebilir mi var?
NeilS

Android 5.0.1 jy Huawei hala etkileniyor.
southerton
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.