Home > Software design >  How to allow buttons in Android development to scale without changing their shape?
How to allow buttons in Android development to scale without changing their shape?

Time:09-08

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

What I would like to happen is, 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 failed):

enter image description here

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

CodePudding user response:

This can be achived by trimming stroked path on your vector drawable. More info over here: https://www.androiddesignpatterns.com/2016/11/introduction-to-icon-animation-techniques.html#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>

CodePudding user response:

AFAIK, There is no 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.

What I suggest is 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.

  • Related