I have a scenario in which I want to set a Drawable
depending upon the theme defined.
To explain this further, Here is what I have in code:
\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>
So as you have noticed I am defining a custom attr homeIcon and setting the attribute value in AppTheme.
When I define this attribute in a layout XML and try to access it it works smoothly
<ImageView android:id="@+id/img" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="?attr/homeIcon" />
and renders the Drawable
ic_home in an ImageView
.
But I am not able to figure out how to access the Drawable
programmatically.
I tried to do this with a work around, by defining a holder LayerList Drawable
, which results in resource not found exception:
<?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>
Summary I want to access the
Drawable
defined in a custom definedTheme
programmatically.
An <attr> element has two xml attributes name and format . name lets you call it something and this is how you end up referring to it in code, e.g., R. attr. my_attribute . The format attribute can have different values depending on the 'type' of attribute you want.
Resources are the additional files and static content that your code uses, such as bitmaps, layout definitions, user interface strings, animation instructions, and more. You should always externalize app resources such as images and strings from your code, so that you can maintain them independently.
The res/values folder is used to store the values for the resources that are used in many Android projects to include features of color, styles, dimensions etc.
drawable for all drawable resources) and for each resource of that type, there is a static integer (for example, R. drawable. icon ). This integer is the resource ID that you can use to retrieve your resource.
I think you can get the Drawable with this code:
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();
Another possible way to do it:
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; }
Or in Kotlin:
@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 }
no need to recycle anything here...
usage:
int drawableResId=getResIdFromAttribute(this,R.attr.homeIcon); Drawable drawable = getResources().getDrawable(drawableResId);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With