Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent android layer drawable shapes (e.g. circle) from scaling

I try to create a simple illustration using XML layer-list drawable.
I have two shapes, a circle and a rectangle
I want a circle not to scale.
The following is the layout:

<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>

    <ImageView
        android:layout_margin="10dp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:src="@drawable/shape5"
        android:layout_gravity="center"
        android:scaleType="center"
        />
</LinearLayout>

And this is the shape5.xml drawable

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:top="0dp" android:left="0dp">
        <shape android:shape="rectangle" android:scaleType="center">
            <stroke android:width="2dp" android:color="@android:color/holo_red_light" />
            <size android:width="200dp" android:height="100dp"/>
        </shape>
    </item>

    <item android:top="10dp" android:left="10dp">
        <shape android:shape="oval" android:gravity="center" android:scaleType="center" >
            <stroke android:width="2dp" android:color="@android:color/holo_blue_light" />
            <corners android:radius="10dp" />
            <size android:width="20dp" android:height="20dp"/>

        </shape>
    </item>
</layer-list>

The resulting drawing looks like this:

screenshot of the rendered activity

it is clear that item android:top does the work, but nothing prevents shape from scaling. size width does not work, android:scaleType="center" does not work either.

I looked quickly at LayerDrawable.java implementation. Seems like behind the scenes an inset is created from item attributes. So I guess by calculating those I can achieve the result, I want. Is that the only way?

Update:

As per this answer, I knew that manipulating item's android:top, android:left etc, I can create a virtual inset that will scale my "shapes" as I want them. I checked this, and it is correct. So it is a workaround. I however am sorely disappointed with how counter-intuitive it is. I still hope someone can point me to a simple way to disable scaling.

Update: As per this Google Android documentation page, setting ImageView scaleType should have prevented scaling. Apparently in my case it did not work. Something is missing.

like image 424
Michael Kariv Avatar asked Mar 31 '14 17:03

Michael Kariv


1 Answers

Give your circle drawable the same height and width like so:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
  android:shape="oval" >
    <solid 
      android:color="@color/grey" />
    <size 
      android:width="16dp"
      android:height="16dp"/>
</shape>

The values you put as height and width do not matter too much, the important thing is that height = width. Think of them as aspect ratio and you want a ratio for a perfect circle, which is 1:1.

The reason you don't have to worry about the exact values is because the drawable will scale via the scaleType attribute.

Once you have inserted the drawable into your ImageView you can set the scaleType to scale it:

scaleType = fitCenter -> Drawable will be the same size as the ImageView but will stay a perfect circle! scaleType = centerInside -> Drawable will be height and width you specified in the parameter etc ...

like image 155
A. Steenbergen Avatar answered Oct 20 '22 21:10

A. Steenbergen