How can I allow buttons in Android development to scale without changing their shape?

94 Views Asked by At

Say we got this button in a layout file, say app/res/layout/activity_main.xml:

   <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:background="@drawable/test"
        android:text="ok" />

Also say that @drawable/test is an SVG file (vector image) that gives a unique shape for the button as follows:

Enter image description here

The problem that I have is that when the text android:text="sadfsdafsadfsadfsadfsdfsdafsdf" is long, the button's shape gets ruined as follows:

Enter image description here

As the button is stretched horizontally, I want only to stretch the button from the middle, without harming its shape on the sides.

This is the desired outcome (trying to achieve it, but so far it failed):

Enter image description here

I heard of 9-patch files, but sadly they only work for bitmaps. About vector files: how can we maintain their shapes when scaled?

2

There are 2 best solutions below

4
Michal On

This can be achieved by trimming stroked path on your vector drawable.

More information is in Trimming stroked paths.

Example:

<animated-vector
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt">
    <aapt:attr name="android:drawable">
        <vector
            android:name="vector"
            android:width="500dp"
            android:height="500dp"
            android:viewportWidth="500"
            android:viewportHeight="500">
            <path
                android:name="path"
                android:pathData="M 120 80 L 160 120 L 120 160 L 160 160 L 160 80 L 120 80"
                android:fillColor="#31a8f7"
                android:strokeColor="#31a8f7"
                android:strokeWidth="1"/>
            <path
                android:name="path_1"
                android:pathData="M 320 120 L 160 120"
                android:strokeColor="#31a8f7"
                android:strokeWidth="81"/>
            <path
                android:name="path_2"
                android:pathData="M 320 160 L 360 120 L 320 80 Z"
                android:fillColor="#31a8f7"
                android:strokeColor="#31a8f7"
                android:strokeWidth="1"/>
        </vector>
    </aapt:attr>
    <target android:name="path_1">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="trimPathStart"
                    android:duration="150"
                    android:valueFrom="0.6"
                    android:valueTo="0"
                    android:valueType="floatType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="trimPathStart"
                    android:startOffset="150"
                    android:duration="150"
                    android:valueFrom="0"
                    android:valueTo="0.6"
                    android:valueType="floatType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
    <target android:name="path_2">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="pathData"
                    android:duration="150"
                    android:valueFrom="M 220 160 L 260 120 L 220 80 Z"
                    android:valueTo="M 320 160 L 360 120 L 320 80 Z"
                    android:valueType="pathType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="pathData"
                    android:startOffset="150"
                    android:duration="150"
                    android:valueFrom="M 320 160 L 360 120 L 320 80 Z"
                    android:valueTo="M 220 160 L 260 120 L 220 80 Z"
                    android:valueType="pathType"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
</animated-vector>
0
Sreehari K On

AFAIK, there isn't any direct way to achieve this without using a 9-patch. Either you will need to make the head and tail portion for the button into a different views if and only if you need to use a vector.

I suggest to make a PNG copy of this vector and use 9 patch of it. If you're concerned about the size, then it won't cost much for 9-patch images.