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.
Classic drawable resources such as images are stored in the drawable folder. In contrast, vector drawables are stored in drawable-v24 . For this project, keep the drawable default and click OK. You should now see the New File dialog box.
Supported file types are PNG (preferred), JPG (acceptable), and GIF (discouraged).
A drawable resource is a general concept for a graphic that can be drawn to the screen and which you can retrieve with APIs such as getDrawable(int) or apply to another XML resource with attributes such as android:drawable and android:icon .
Sometimes you want an outline around your shape and to do that you can use the stroke tag. You can specify the width and color of the outline using android:width and android:color.
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
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