드로어 블에서 스타일 속성을 참조하는 방법은 무엇입니까?


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>

이 방법은 훌륭하게 작동하여 여러 테마를 쉽게 만들고 수정할 수 있습니다. 문제는 드로어 블이 아닌 뷰에서만 사용할 수 있다는 것입니다 .

예를 들어 레이아웃 내에서보기의 값을 참조하면 다음과 같이 작동합니다.

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

하지만 드로어 블에서 똑같이하는 것은 다음과 같습니다.

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

아직 해결책이 없습니까? 나는 똑같은 벽
Guillaume

또 다른 최근 질문 : stackoverflow.com/q/12115125/317889 같은 문제입니다. Google에서 정렬하십시오.
HGPB 2012 년

3
여기에 지정된대로 분명히이 문제는 안드로이드 L 미리보기에서 해결되었다 : code.google.com/p/android/issues/detail?id=26251
비앙카 Daniciuc

답변:


161

내 경험상 XML 드로어 블의 속성을 참조하는 것은 불가능합니다.
테마를 만들려면 다음이 필요합니다.

  • 테마 당 하나의 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에서 고정되어 있고 테마 색상이 잘 참조되지만 동일한 코드가 다른 pre-L 장치에서 실행되고 실제로 attr 참조가 작동하지 않습니다. pre-L 장치! LoL .. 그래서 어쨌든 다른 드로어 블을 유지해야한다면 그것은 고정되어 있지 않습니다.
Davideas

2
나는 이것을 두 번 찬성 할 수 있으면 좋겠다. 하드 코딩 된 #RGB 대신 참조를 사용하도록 내 셰이프를 간소화하려고했는데 동일한 오류가 발생했습니다. 해결책을 찾기 위해 왔고 2 주 전에 upvoted와 동일한 답변을 찾았습니다! (facepalm)
Tiksi

2
이것은 슈퍼 닌자입니다!
MariusBudin

4
아아! 이것은 Google이 백 포트 수정을 수행하는 데 최우선 순위 여야합니다! ? attr-reference 표기법은 매우 유용하고 중요하여 앱 내에 여러 테마가있는 경우 없이는 살 수 없을 정도로 매우 유용합니다. 지금 당장은 각 사용자 정의 버튼 유형에 대해 3 개의 드로어 블 XML을 만들어야합니다!
Stephan Henningsen

2
그게 내가 원하는거야. <21 SDK의 매우 간단하고 멋진 솔루션입니다.
Adnan Abdollah Zaki

20

시작 lollipop이 기능이 지원됩니다 (API 21)을 참조 https://code.google.com/p/android/issues/detail?id=26251

그러나 롤리팝이없는 장치를 대상으로하는 경우 충돌이 발생하므로 사용하지 마십시오. 대신 허용 된 답변의 해결 방법을 사용하십시오.


사전 L API에서 작동하도록 지원 라이브러리의 종류를 사용할 기회가 있습니까?
이반

2
아니요, 지원 라이브러리는 이전 기기에서 사용할 수있는 API 세트입니다.이 동작 변경은 컴파일러 및 빌드 도구에 있으므로 지원 라이브러리와 관련이 없습니다.
marmor

3
아니요, 롤리팝에서는 구현 된 기능이 아니라 눈에 띄는 버그 수정이었습니다. 그리고 그것에 대한 심각한 버그.
아드리안 Sicaru

젠장, 좋은 테마 솔루션이 있다고 생각했습니다. 이제 돌아가서 버튼 선택기 드로어 블을 만들어야합니다.
filthy_wizard

4

롤리팝 이전 기기의 드로어 블에서 스타일 속성을 참조 할 수는 없지만 색상 상태 목록은 가능합니다. 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의 이전 버전 (사전 롤리팝)에서 작동하도록하는 것입니다.

안타깝게도 유사한 드로어 블 메서드 는 스타일 속성과 함께 작동하지 않습니다.


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의 안드로이드 지원 라이브러리는이 기능의 버그 무료 구현을 가지고있다. 간단하게 당신의 용도를 교체 ImageView와 함께 AppCompatImageView.


2
희망찬 소리! 그러나 문제는보기가 아닌 Drawable 모양에 있습니다. 테마 색상을 얻기 위해 attr을 사용하는 모양을 (배경으로) 참조하는 appcompat 뷰가 있으며 <21에서 위의 오류가 발생합니다. 내가 놓친 appcompat 드로어 블이 있습니까?
NeilS

Android 5.0.1 jy Huawei는 여전히 영향을받습니다.
southerton
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.