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


96

アプリケーションに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>

この方法はすばらしいので、いくつかのテーマを簡単に作成および変更できます。問題は、ビューでのみ使用でき、Drawableでは使用できないように見えることです。

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

 <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が、同じことが起こります。

どうすればこれができますか?そしてなぜそれはビューでは機能するがドローアブルでは機能しないのですか?この制限はドキュメントのどこにも見つかりません...


:これは、次の質問の重複であるかもしれないstackoverflow.com/questions/7529574/...
ポールLammertsma

@Martin M.、これで何を考えましたか?
user123321 2011

そのための解決策はまだありますか?私はまったく同じ壁にぶつかっています
ギヨーム

ここで別のより最近の質問:stackoverflow.com/q/12115125/317889同じ問題。Googleで整理してください。
HGPB 2012

3
どうやらこの問題は、ここに指定されているように、Android Lプレビューで解決されました:code.google.com/p/android/issues/detail?id
Bianca Daniciuc

回答:


161

私の経験では、XMLドローアブルの属性を参照することはできません。
テーマを作成するには、次のことを行う必要があります。

  • テーマごとに1つのXMLドローアブルを作成します。
  • @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" />

20
互換性を維持したい場合は、このソリューションがまだ必要であるようです... Lから修正され、テーマの色はよく参照されていますが、同じコードが異なるL以外のデバイスで実行され、実際にはattr参照が機能しませんL以前のデバイス!LoL ..だからとにかく私が別のドローアブルを維持する必要があるかどうかは固定されていません。
Davideas、

2
私はこれを2回賛成できるといいのですが。ハードコードされた#RGBの代わりに参照を使用するように図形を合理化しようとしたところ、同じエラーが発生しました。ソリューションを求めてSOに来て、2週間前に私が賛成したこの同じ答えを見つけました!(facepalm)
Tiksi

2
これは超忍者です!
MariusBudin

4
ARGH!これは、Googleがバックポート修正を行うための最優先事項です。?attr-reference表記は非常に便利で重要であり、アプリ内に複数のテーマがある場合、それなしでは生活することはほぼ不可能です。現在、カスタムボタンタイプごとに3つの描画可能なXMLを作成する必要があります。
Stephan Henningsen 2016年

2
それが欲しい。21 SDK未満の非常にシンプルで優れたソリューション。
Adnan Abdollah Zaki 2017年

20

以降ではlollipop、この機能がサポートされている(API 21)を参照してください https://code.google.com/p/android/issues/detail?id=26251

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


ある種のサポートライブラリを使用してそれをL以前のAPIで動作させる機会はありますか?
イワン

2
いいえ、サポートライブラリは古いデバイスで使用できるAPIのセットです。この動作の変更はコンパイラとビルドツールにあるため、サポートライブラリとは関係ありません。
2015年

3
いいえ、ロリポップでは実装された機能ではなく、目立ったバグ修正でした。そしてそれで深刻なバグ。
Adrian Sicaru

いまいましい、私は素晴らしいテーマ解決策があると思った。次に戻って、ボタンセレクタードローアブルの束を作成する必要があります。
filthy_wizard

4

Lollipop以前のデバイスでは、ドローアブルからスタイル属性を参照することはできませんが、カラーステートリストでは可能です。AndroidサポートライブラリのAppCompatResources.getColorStateList(Context context、int resId)メソッドを使用できます。欠点は、これらのカラー状態リストをプログラムで設定する必要があることです。

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

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サポートライブラリがAndroidの古いバージョン(Lollipop以前)で動作するようにするためのものです。

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


1

私はhttps://stackoverflow.com/a/59467269/3841352で同じ質問に答えましたが、ここにも投稿します:

同じ問題が発生しましたが、2019年現在は解決されていないため、セレクターで参照可能な属性をドローアブルとして使用できません。ここに投稿されていないので、問題の解決策を共有します。バグレポートの最後のコメントで見つけました。

回避策は基本的に、属性値を参照するリソースとなる描画可能なリソースを作成することです。

あなたのケースを説明するために、解決策は次の代わりになります:

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

ドローアブルリソースの?attr / *を置き換えます。

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

ドローアブルは次のように定義されます。

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>

それが役に立てば幸い!!


0

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

AppCompatImageViewV7でのAndroidのサポートライブラリは、この機能のバグフリーな実装を持っています。単にあなたの用法を交換ImageViewしてAppCompatImageView


2
いいですね!しかし、問題はビューではなくドローアブル形状にあります。attrを使用してテーマの色を取得するシェイプを(背景として)参照するappcompatビューがあり、<21で上記のエラーでフォールオーバーします。私が見逃したappcompatのドローアブルはありますか?
NeilS

Android 5.0.1 jy Huaweiはまだ影響を受けています。
サウザートン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.