Search code examples
androidcanvasdrawableandroid-drawablexml-drawable

XML drawable scale when drawing on canvas


I'm trying to make a drawable that looks like circle with shadow. It needs to scale to different sizes and needs to be drawn on a canvas. I use setBounds to set coords and scale.

My drawable:

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:bottom="0dp"
        android:left="5dp"
        android:right="5dp"
        android:top="10dp">
        <shape android:shape="oval">
            <size
                android:width="115dp"
                android:height="115dp" />
            <solid android:color="@color/level_button_dark" />
        </shape>
    </item>
    <item
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp">
        <shape android:shape="oval">
            <size
                android:width="115dp"
                android:height="115dp" />
            <solid android:color="@color/level_button" />
        </shape>
    </item>
</layer-list>

My drawing code

mButtonDrawable.setBounds(20, 20, 220, 220);
mButtonDrawable.draw(canvas);
mButtonDrawable.setBounds(270, 20, 370, 120);
mButtonDrawable.draw(canvas);
mButtonDrawable.setBounds(420, 20, 470, 70);
mButtonDrawable.draw(canvas);

Result:

enter image description here

I want to achieve a consistent look for all scales. Tested on emulator api 18.


Solution

  • While @RexSplode approach is valid I found a way to do it with one drawable. You just shouldn't call setBounds() and operate with canvas.

    See example below.

    mButtonDrawable.setBounds(0, 0, mButtonDrawable.getIntrinsicWidth(), mButtonDrawable.getIntrinsicHeight());
    
    canvas.save();
    canvas.translate(20, 20);
    canvas.scale(1, 1);
    mButtonDrawable.draw(canvas);
    canvas.restore();
    
    canvas.save();
    canvas.translate(420, 20);
    canvas.scale(0.5f, 0.5f);
    mButtonDrawable.draw(canvas);
    canvas.restore();
    
    canvas.save();
    canvas.translate(620, 20);
    canvas.scale(0.25f, 0.25f);
    mButtonDrawable.draw(canvas);
    canvas.restore();
    

    Result:

    enter image description here

    I got an idea from ImageView source.