6

I'm trying to achieve something similar to the BEMAnimationTypeStroke which can be found in the iOS library BEMCheckBox.

I've tried using an animated vector drawable to achieve this, but I do not know how to animate the checkmark inside the circle from an 0 start point to the final position. (the circle can be static, I'm looking to animate the check mark). This is the implementation I tried for this:

drawable/vector_drawable_ic_check_circle_white_48px.xml

    <path
            android:name="check"
            android:fillColor="#FFFFFF"
            android:pathData="M37.1,13.6L18.4,32.3h1.7l-8.5-8.5L10,25.5l8.5,8.5l0.8,0.8l0.8-0.8l18.7-18.7L37.1,13.6L37.1,13.6z"/>
    <path
            android:name="circle"
            android:fillColor="#FFFFFF"
            android:pathData="M24,48c13.3,0,24-10.7,24-24S37.3,0,24,0S0,10.7,0,24S10.7,48,24,48L24,48z
M24,45.6
C12.1,45.6,2.4,35.9,2.4,24S12.1,2.4,24,2.4S45.6,12.1,45.6,24S35.9,45.6,24,45.6L24,45.6z"/>
</vector>

anim/transform.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
            android:duration="1000"
            android:propertyName="fillColor"
            android:valueFrom="@color/transparent"
            android:valueTo="@color/white"/>
</set>

drawable/animation.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/vector_drawable_ic_check_circle_white_48px">
    <target
            android:name="check"
            android:animation="@anim/change_color"/>
</animated-vector>

And when the layout is set, I start the animation using:

ImageView mCpuImageView = (ImageView) findViewById(R.id.animated_check);
Drawable drawable = mCpuImageView.getDrawable();
if (drawable instanceof Animatable) {
    ((Animatable) drawable).start();
}

Can anyone help me with this? Is there an easier way to achieve this (Custom view or existing library)?

The idea is that I want to have an check mark in a circle and I want to animate the path of the check mark. When it is displayed only the circle will be visible and afterwards to animate the check mark creation. If other customizations, like animating the circle at the same time the check mark is animating are easy to implement It would be event better, but at first I want to animate the check mark only.

LE: In the end I've chosen to go with the approach of creating the animation manually via an custom View. If anyone has an idea of how I can achieve this via vector drawable it woul be a nice development practice. Thank you.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Ionut Negru
  • 6,186
  • 4
  • 48
  • 78

5 Answers5

14

I was looking for the same, this post pretty much explains it all. The code from that post:

drawable/check_mark.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportHeight="24.0"
    android:viewportWidth="24.0">
    <group android:name="background">
        <path
            android:name="circle"
            android:fillColor="@color/colorPrimary"
            android:pathData="M12,12m-10,0a10,10 0,1 1,20 0a10,10 0,1 1,-20 0" />
    </group>
    <group android:name="check">
        <path
            android:name="tick"
            android:pathData="M6,11 l0,0 l0,0"
            android:strokeColor="@color/colorAccent"
            android:strokeWidth="1" />
    </group>

</vector>

drawable-v21/animated_check.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/check_mark">
    <target
        android:name="tick"
        android:animation="@anim/check_animation" />
</animated-vector>

anim/check_animation.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/accelerate_interpolator"
    android:ordering="sequentially"
    android:shareInterpolator="false">
    <!-- Step 1 -->
    <objectAnimator
        android:duration="@android:integer/config_shortAnimTime"
        android:propertyName="pathData"
        android:valueFrom="M6,11 l0,0 l0,0"
        android:valueTo="M6,11 l3.5,4 l0,0"
        android:valueType="pathType" />
    <!-- Step 2 -->
    <objectAnimator
        android:duration="@android:integer/config_shortAnimTime"
        android:propertyName="pathData"
        android:valueFrom="M6,11 l3.5,4 l0,0"
        android:valueTo="M6,11 l3.5,4 l8,-7"
        android:valueType="pathType" />
</set>

Usage

Layout XML

<ImageView
    android:id="@+id/imageView"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:visibility="visible"
    app:srcCompat="@drawable/animated_check" />

Java Class

mImgCheck = (ImageView) findViewById(R.id.imageView);
((Animatable) mImgCheck.getDrawable()).start();
Daksh Agrawal
  • 855
  • 1
  • 11
  • 22
s-hunter
  • 24,172
  • 16
  • 88
  • 130
9

You can do this by using Lottie Library which is folks at Airbnb.

It has large icons sets and animation that can be easily integrated using both Android development language i.e; Java and Kotlin.

And here is the link to your tick animation that you were looking for.

To use this icon you need to download the json file of this icon and add it into your assets folder and follow the instruction from documentations.

Himanshu Agarwal
  • 4,623
  • 5
  • 35
  • 49
  • Thank you. It is a good option indeed. I'm not working on this feature anymore (got it solved with other solutions), but maybe it could help others. – Ionut Negru Feb 25 '19 at 12:49
1

The animation of the check mark creation can be achieved by animating the check mark path's trimPathEnd attribute (see https://developer.android.com/reference/android/graphics/drawable/VectorDrawable.html). The value of the trimPathEnd attribute means the percentage of the path where the end should be, trimming everything that's beyond that percentage. By animating trimPathEnd from 0 to 1 would reveal from 0% to 100% of the check mark path.

In the following AnimatedVectorDrawable definition, we reference an animation named trim_path:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/vector_drawable_ic_check_circle_white_48px">
    <target
            android:name="check"
            android:animation="@anim/trim_path"/>
</animated-vector>

Then in anim/trim_path.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
            android:duration="1000"
            android:propertyName="trimPathEnd"
            android:valueFrom="0"
            android:valueTo="1"/>
</set>

This should produce an AnimatedVectorDrawable that has a check mark growing from 0% to 100%. Similarly, you could animate trimPathEnd on the circle as well. Note you may need to duplicate the circle path, so one circle is gray and static, the other circle is blue and animating on top.

Doris Liu
  • 807
  • 5
  • 9
  • The `mCpuImageView.getDrawable()` gives me a drawable which is a `VectorDrawable` instance, not `Animatable` – kdas Feb 24 '17 at 16:39
0

This solution written in one xml file:

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:aapt="http://schemas.android.com/aapt"
    xmlns:tools="http://schemas.android.com/tools"
    tools:targetApi="lollipop">
    <aapt:attr name="android:drawable">
        <vector
            android:width="50dp"
            android:height="50dp"
            android:viewportWidth="24.0"
            android:viewportHeight="24.0">
            <group android:name="check">
                <path
                    android:name="done"
                    android:pathData="M6,11 l0,0 l0,0"
                    android:strokeWidth="1"
                    android:strokeColor="@color/black" />
            </group>

        </vector>
    </aapt:attr>
    <target android:name="done">
        <aapt:attr name="android:animation">
            <set
                android:interpolator="@android:anim/accelerate_interpolator"
                android:ordering="sequentially"
                android:shareInterpolator="false">
                <!-- Step 1 -->
                <objectAnimator
                    android:duration="@android:integer/config_shortAnimTime"
                    android:propertyName="pathData"
                    android:valueFrom="M6,11 l0,0 l0,0"
                    android:valueTo="M6,11 l3.5,4 l0,0"
                    android:valueType="pathType" />
                <!-- Step 2 -->
                <objectAnimator
                    android:duration="@android:integer/config_shortAnimTime"
                    android:propertyName="pathData"
                    android:valueFrom="M6,11 l3.5,4 l0,0"
                    android:valueTo="M6,11 l3.5,4 l8,-7"
                    android:valueType="pathType" />
            </set>
        </aapt:attr>
    </target>
Androidz
  • 261
  • 2
  • 11
-1

It works for me. Just follow the xml code of @s-hunter above. in you activity modify the code. like below:

mImgCheck = (ImageView) findViewById(R.id.imageView);        
Drawable drawable = mImgCheck.getDrawable();
((Animatable) drawable).start();

You can add rippleBackground for better look.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Asesha George
  • 2,232
  • 2
  • 32
  • 68