Reputation: 10672
Let's say I have a simple shape drawable that draws a ring as follows:
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:dither="true"
android:innerRadiusRatio="3"
android:shape="ring"
android:thicknessRatio="36"
android:useLevel="false" >
<gradient
android:centerColor="@android:color/holo_blue_bright"
android:centerY="0.001"
android:endColor="@android:color/holo_blue_dark"
android:gradientRadius="202.5"
android:startColor="@android:color/transparent"
android:type="radial"
android:useLevel="false" />
</shape>
And I apply this shape as a view background as follows:
<View
android:layout_width="96dp"
android:layout_height="96dp"
android:padding="16dp"
android:background="@drawable/custom_shape" />
The exact details of the shape are not relevant for this question - just suffice to say I have a shape. Now, I don't want to hard-code the various parameters for the shape. Let's take thicknessRatio
as an example. If i wanted the thickness ratio to change depending on say, screen configuration, I'd of course use an integer resource as follows. I'd have a values.xml with the following:
<item name="thickness_ratio" type="integer" format="integer">56</item>
And then, android:thicknessRatio="@integer/thickness_ratio"
.
So far, so good. Now, I also want to have two "flavors" of my my shape drawable - a "large" one and a "small" one, and I wish to query the thickness ratio depending not on configuration, but on the style applied to the View. Which is what styles and themes are for. So, here's what I tried:
<resources>
<attr name="thicknessRatio" format="reference" />
</resources>
<style name="CustomShapeSmall">
<item name="thicknessRatio">@integer/thickness_ratio_small</item>
</style>
<style name="CustomShapeLarge">
<item name="thicknessRatio">@integer/thickness_ratio_large</item>
</style>
<item name="thickness_ratio_small" type="integer" format="integer">32</item>
<item name="thickness_ratio_large" type="integer" format="integer">56</item>
android:thicknessRatio="?attr/thicknessRatio"
View
:<View
android:layout_width="96dp"
android:layout_height="96dp"
android:padding="16dp"
style="@style/CustomShapeSmall"
android:background="@drawable/custom_shape" />
Unfortunately, this does not work. I get the following exception:
Caused by: android.content.res.Resources$NotFoundException: File res/drawable/custom_shape.xml from drawable resource ID #0x7f020000
at android.content.res.Resources.loadDrawable(Resources.java:2091)
at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
at android.view.View.<init>(View.java:3364)
at android.view.View.<init>(View.java:3293)
... 28 more
Caused by: java.lang.NumberFormatException: Invalid float: "?2130771969"
at java.lang.StringToReal.invalidReal(StringToReal.java:63)
at java.lang.StringToReal.parseFloat(StringToReal.java:310)
at java.lang.Float.parseFloat(Float.java:300)
at android.content.res.TypedArray.getFloat(TypedArray.java:287)
at android.graphics.drawable.GradientDrawable.inflate(GradientDrawable.java:827)
at android.graphics.drawable.Drawable.createFromXmlInner(Drawable.java:901)
at android.graphics.drawable.Drawable.createFromXml(Drawable.java:837)
at android.content.res.Resources.loadDrawable(Resources.java:2087)
From the exception stack trace, it appears that the line android:thicknessRatio="?attr/thicknessRatio"
resolves to a question mark followed by the integer value of R.attr.thicknessRatio
- however no further resolution is performed to actually query the value of this attribute.
What am I missing here?
Here is the complete github project for this issue.
Upvotes: 7
Views: 3777
Reputation: 20563
Apparently, it's not possible to correctly reference attributes in xml drawables.
The workaround is to create different drawables (one with the small ratio and one with the large) and use these in your separate styles. Then you can apply those styles to your views.
I've sent you a pull request that demonstrates this:
https://github.com/curioustechizen/so-question-android-custom-styles/pull/1
also see:
https://stackoverflow.com/a/13471695/1369222
Upvotes: 6