Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shape Drawable parameters depending on applied style

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:

Step 1: Declare an attribute for thickness ratio (attrs.xml):

<resources>
        <attr name="thicknessRatio" format="reference" />
</resources>

Step 2: Declare two styles utilizing this attribute (styles,xml):

<style name="CustomShapeSmall">
    <item name="thicknessRatio">@integer/thickness_ratio_small</item>
</style>

<style name="CustomShapeLarge">
    <item name="thicknessRatio">@integer/thickness_ratio_large</item>
</style>

Step 3: Define the two integers in values.xml:

<item name="thickness_ratio_small" type="integer" format="integer">32</item>
<item name="thickness_ratio_large" type="integer" format="integer">56</item>

Step 4: Query the custom attribute in the Shape Drawable:

android:thicknessRatio="?attr/thicknessRatio"

Step 5: Apply the desired style to the 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?


EDIT:

Here is the complete github project for this issue.

like image 402
curioustechizen Avatar asked Nov 22 '13 08:11

curioustechizen


People also ask

What is v24 in android drawable?

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.

What is the preferred image format for the Drawables?

Supported file types are PNG (preferred), JPG (acceptable), and GIF (discouraged).

Which attribute is used to draw a drawable at the bottom of text on a button?

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 .

What is stroke in android XML?

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.


1 Answers

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

like image 193
Anup Cowkur Avatar answered Oct 21 '22 05:10

Anup Cowkur