How to create a "Waze like" progress button in Android:

365 views Asked by At

I'm looking for a way to produce a button with progress functionality (the button is pressed at the end of the progress...) like in Waze, here in an example (the "Go now" button):

enter image description here

I found this solution:

Create rectangle border progress bar in android

And here is the result of the implementation made there:

enter image description here

But unfortunately this is not good enough (I can't changes the button corner radius to something round and the side progresses moving in a different speed the the top and the bottom progress).

From a check I made the Waze app creates the progress using a canvas and by painting paths on it. How can this be done?

1

There are 1 answers

0
C.F.G On

After some search, I found many posts that almost solved the above problem for API+14 (I haven't tested on API< 21):

Using AnimatedVectorDrawable:

First draw and animate a rectangular drawable. (my example is a sharp (and looks ugly) rectangle, you can replace it with a rounded corners)

<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="24dp"
            android:height="24dp"
            android:viewportWidth="24"
            android:viewportHeight="24">
                <path android:name="path"
                    android:pathData="M0,0 L24,0 L24,24 L0,24 L 0,0 z"
                    android:fillColor="#00FFFFFF"
                    android:strokeColor="#B71C1C"
                    android:strokeWidth="1"
                    android:strokeLineCap="round"
                    android:strokeLineJoin="round"/>
        </vector>
    </aapt:attr>
    <target android:name="path">
        <aapt:attr name="android:animation">
            <set>
                <objectAnimator
                    android:propertyName="trimPathStart"
                    android:duration="1500"
                    android:valueFrom="1"
                    android:valueTo="0"
                    android:valueType="floatType"
                    android:repeatMode="reverse"
                    android:repeatCount="infinite"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
                <objectAnimator
                    android:propertyName="trimPathOffset"
                    android:duration="1500"
                    android:valueFrom="0"
                    android:valueTo="1"
                    android:valueType="floatType"
                    android:repeatCount="infinite"
                    android:interpolator="@android:interpolator/fast_out_slow_in"/>
            </set>
        </aapt:attr>
    </target>
</animated-vector>

then use the following codes to setup and start the animation for API+14: (Source: https://stackoverflow.com/a/64237793/6576302)

AnimatedVectorDrawableCompat drawable = AnimatedVectorDrawableCompat.create(
    this, // your Context
    R.drawable.animation);

CardView button = findViewById(R.id.yourButton); //<--- foreground is not availible for button

button.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        button.setForeground(drawable); //<----
        drawable.start();
    }
});

OUTPUT:

enter image description here

P.S. I put the animated drawable into a cardView's foreground because I couldn't reach this property for button.

Here and Here are another solutions in Kotlin. (But I am not sure about its API compatibility version to support +14 or +17)