Доступ к ресурсу, определенному в theme и attrs.xml android - PullRequest
33 голосов
/ 09 января 2012

У меня есть сценарий, в котором я хочу установить Drawable в зависимости от определенной темы.

Чтобы объяснить это далее, вот что у меня в коде:

\ res \ values ​​\ attrs.xml

<resources>
    <declare-styleable name="AppTheme">
        <attr name="homeIcon" format="reference" />
    </declare-styleable>
</resources>

res \ values ​​\ styles.xml

<resources>
    <style name="AppTheme" parent="android:style/Theme">
        <item name="attr/homeIcon">@drawable/ic_home</item>
    </style>
</resources>

AndroidManifest.xml

    <application android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity" android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

Итак, как вы заметили, я определяю собственный атрибут attr homeIcon и задаю значение атрибута в AppTheme.

Когда я определяю этот атрибут в XML-макете и пытаюсь получить доступон работает гладко

<ImageView android:id="@+id/img"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:src="?attr/homeIcon" />

и отображает Drawable ic_home в ImageView.

Но я не могу понять, как получить программный доступ к Drawable.

Я попытался сделать это с обходным путем, определив держатель LayerList Drawable, в результате чего ресурс не нашел исключение:

<?xml version="1.0" encoding="utf-8"?>
<layer-list
    xmlns:android="http://schemas.android.com/apk/res/android" >
    <item
        android:drawable="?attr/homeIcon" />
</layer-list>

Сводка Я хочу получить программный доступ к Drawable, определенному в пользовательском Theme.

Ответы [ 5 ]

70 голосов
/ 09 января 2012

Я думаю, вы можете получить Drawable с этим кодом:

TypedArray a = getTheme().obtainStyledAttributes(R.style.AppTheme, new int[] {R.attr.homeIcon});     
int attributeResourceId = a.getResourceId(0, 0);
Drawable drawable = getResources().getDrawable(attributeResourceId);
a.recycle();
10 голосов
/ 19 ноября 2014

Другой возможный способ сделать это:

  public static int getResIdFromAttribute(final Activity activity,final int attr)
    {
    if(attr==0)
      return 0;
    final TypedValue typedvalueattr=new TypedValue();
    activity.getTheme().resolveAttribute(attr,typedvalueattr,true);
    return typedvalueattr.resourceId;
    }

Или в Котлине:

@JvmStatic
fun getResIdFromAttribute(activity: Activity, attr: Int): Int {
    if (attr == 0)
        return 0
    val typedValue = TypedValue()
    activity.theme.resolveAttribute(attr, typedValue, true)
    return typedValue.resourceId
}

здесь не нужно ничего перерабатывать ...

использование:

int drawableResId=getResIdFromAttribute(this,R.attr.homeIcon);
Drawable drawable = getResources().getDrawable(drawableResId);
2 голосов
/ 30 декабря 2015

Я использовал метод ниже, чтобы получить атрибут стиля формы идентификатора ресурса.Затем его можно использовать для рисования, строки, размеров и т. Д.

TypedArray typedArray = context.getTheme().obtainStyledAttributes(new int[] { R.attr.attrName });   
int resourceId = typedArray.getResourceId(0, defaultResourceId);
typedArray.recycle();

ура: -)

1 голос
/ 03 апреля 2017

Вот результаты моего исследования по этой теме. Если у нас есть declare-stylable, то мы можем переопределить эти значения в темах.

На данный момент лучший способ найти их - это следующее.

TypedArray a = context.getTheme().obtainStyledAttributes(R.styleable.AppTheme);
a.getDrawable(R.styleable.AppTheme_homeIcon);

Используя R.styleable.AppTheme_homeIcon, мы ссылаемся именно на тот атрибут, который нам нужен. Например, если у нас будет немного больше атрибутов, мы можем ссылаться на них следующим образом:

a.getColor(R.styleable.AppTheme_color,defaultValue);
a.getDimension(R.styleable.AppTheme_width,defaultWidth);

И если в текущей теме эти атрибуты не были определены, вы получите значения по умолчанию и никаких исключений.

1 голос
/ 06 августа 2015

Если вы используете библиотеку поддержки / дизайна, более простой способ получить отрисовку сейчас -

Context.getDrawable(int)

или

ContextCompat.getDrawable(Context, int)

ссылка - https://plus.google.com/+BenjaminWeiss/posts/M1dYFaobyBM

...