web-dev-qa-db-ja.com

ドロアブルからスタイル属性を参照する方法は?

アプリケーションに2つの選択可能なテーマが必要です。そのために、次のようないくつかの属性を定義しました。

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

次に、次のように両方のテーマを作成しました。

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

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

この方法はうまく機能し、複数のテーマを簡単に作成および変更できます。問題は、それはビューでのみ使用でき、Drawablesでは使用できないように見えることです。

たとえば、レイアウト内のビューからの値の参照は機能します。

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

しかし、Drawableで同じことをしません:

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

アプリケーションの実行時にこのエラーが発生します。

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

?item_backgroundの代わりにハードコードされた色を使用する場合、機能しますが、テーマを使用することはできません。 ?attr:item_backgroundも試しましたが、同じことが起こります。

どうすればこれができますか?また、なぜビューでは機能するのにDrawableでは機能しないのですか? ドキュメント ...のどこにもこの制限はありません.

87
MM.

私の経験では、xml Drawableの属性を参照することはできません。
テーマを作成するには、次のことが必要です。

  • テーマごとに1つのxml drawableを作成します。
  • @colorタグまたは#RGB形式で、ドローアブルに必要な色を直接含めます。

attrs.xmlでドロウアブルの属性を作成します。

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

ドロアブルをtheme.xmlに追加します。

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

属性を使用して、レイアウトでドロウアブルを参照します。

<TextView Android:background="?my_drawable" />
152
L. G.

Lollipop(API 21)以降、この機能はサポートされています。 https://code.google.com/p/Android/issues/detail?id=26251 をご覧ください。

ただし、Lollipopを使用しないデバイスをターゲットにしている場合は、使用しないでください。クラッシュするため、代わりに承認済みの回答の回避策を使用してください。

16
marmor

pre-Lollipopデバイスのドロアブルからスタイル属性を参照することはできませんが、色の状態リストについては可能です。 AppCompatResources.getColorStateList(Context context、int resId) from Android Support Library。欠点は、これらの色状態リストをプログラムで設定する必要があることです。

これは非常に基本的な例です。

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>

色状態リストが必要なウィジェット:

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

そして最も重要なもの:

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

さて、最もエレガントな方法や最短の方法ではありませんが、これはAndroid Support LibraryがAndroidの古いバージョン(pre-Lollipop)で動作させるために行うことです。

残念ながら、ドローアブルの 類似のメソッド はスタイル属性では機能しません。

4
rubo

@marmorが述べたように、これは現在API 21でサポートされています。しかし、Androidのレガシーバージョンをサポートする必要がある私たちにとっては、この機能を使用できます。 v7サポートライブラリを使用すると、最小SDKレベル7までのアプリで引き続き使用できます。

V7のAppCompatImageView Androidサポートライブラリには、この機能のバグのない実装があります。ImageViewの使用をAppCompatImageViewに置き換えるだけです。

0
Benjamin