How to make Heart Fill animation in Android - GeeksforGeeks

16 Oct, 2021
AnimatedVectorDrawable class was introduced in API 21 and is used to animate Vector Drawables beautifully and easily. Using AnimatedVectorDrawable, one can:
Rotate, Scale, Translate VectorDrawables
Animate the VectorDrawable such as fill color etc.
Draw paths and do Path Morphing
An AnimatedVectorDrawable element has a VectorDrawable attribute, and one or more target element(s). The target element can specify its target by android:name attribute, and link the target with the proper ObjectAnimator or AnimatorSet by android:animation attribute.
Approach to draw Heart fill animation:
Create a new heart.xml file in values directory and add the following vector drawable path data and path commands:heart.xmlheart.xml<?xml version="1.0" encoding="utf-8"?><resources>    <!-- geometry -->    <string name="heart_empty_path">        M32.95, 19 C31.036, 19 29.199, 19.8828338 28,        21.2724796 C26.801, 19.8828338 24.964,         19 23.05, 19 C19.6565, 19 17, 21.6321526 17,        24.9945504 C17, 29.1089918 20.74, 32.4713896         26.405, 37.5667575 L28, 39 L29.595, 37.5667575 C35.26,        32.4713896 39, 29.1089918 39, 24.9945504 C39,        21.6321526 36.3435, 19 32.95, 19 L32.95,         19 Z M28.1155, 35.9536785 L28, 36.0572207 L27.8845,        35.9536785 C22.654, 31.2506812 19.2,        28.1444142 19.2, 24.9945504 C19.2, 22.8201635 20.8555,        21.1798365 23.05, 21.1798365 C24.744,         21.1798365 26.394, 22.2643052 26.9715, 23.7520436         L29.023, 23.7520436 C29.606, 22.2643052 31.256,        21.1798365 32.95, 21.1798365 C35.1445,         21.1798365 36.8, 22.8201635 36.8,        24.9945504 C36.8, 28.1444142 33.346,        31.2506812 28.1155, 35.9536785 L28.1155,        35.9536785 Z    </string>      <string name="heart_full_path">        M28, 39 L26.405, 37.5667575 C20.74,        32.4713896 17, 29.1089918 17,         24.9945504 C17, 21.6321526 19.6565,        19 23.05, 19 C24.964, 19 26.801, 19.8828338 28,        21.2724796 C29.199, 19.8828338 31.036, 19 32.95,        19 C36.3435, 19 39, 21.6321526 39, 24.9945504 C39,        29.1089918 35.26, 32.4713896 29.595,        37.5667575 L28, 39 L28, 39 Z    </string>      <string name="heart_clip_hidden">        M18 37 L38 37 L38 37 L18 37 Z    </string>      <string name="heart_clip_shown">        M0 0 L56 0 L56 56 L0 56 Z    </string></resources>Now create a new Android Resource Directory. Right-click on res folder and select Android Resource Directory. Make sure to select resource type as animator.Animators can change the physical properties of the objects. This means that if you move a View to a new location, the touch coordinates will be mapped at the new location without any other intervention.Now create a new empty_heart.xml file in the animator directory. In this file, we mainly define the duration and animation type to the empty_heart.xml. This file is responsible for the animation when the user clicks on the filled heart icon.empty_heart.xmlempty_heart.xml<?xml version="1.0" encoding="utf-8"?><objectAnimator    xmlns:android="http://schemas.android.com/apk/res/android"    android:propertyName="pathData"    android:valueFrom="@string/heart_clip_shown"    android:valueTo="@string/heart_clip_hidden"    android:duration="600"    android:interpolator="@android:interpolator/fast_out_slow_in"    android:valueType="pathType" />Now create a new fill_heart.xml file in animator directory. In this file, we mainly define the duration and animation type to the empty_heart.xml. This file is responsible for the animation when the user clicks on the empty heart icon.fill_heart.xmlfill_heart.xml<?xml version="1.0" encoding="utf-8"?><objectAnimator    xmlns:android="http://schemas.android.com/apk/res/android"    android:propertyName="pathData"    android:valueFrom="@string/heart_clip_hidden"    android:valueTo="@string/heart_clip_shown"    android:duration="800"    android:interpolator="@android:interpolator/fast_out_slow_in"    android:valueType="pathType" />In the next two steps, we will be creating AnimatedVectorDrawable for both empty heart and filled heart.Now create a new avd_heart_empty.xml file in the drawable directory and the following code.avd_heart_empty.xmlavd_heart_empty.xml<?xml version="1.0" encoding="utf-8"?><animated-vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:drawable="@drawable/ic_heart">      <target        android:name="clip"        android:animation="@animator/empty_heart" /></animated-vector>Now create a new avd_heart_fill.xml file in drawable directory and the following code.avd_heart_fill.xmlavd_heart_fill.xml<?xml version="1.0" encoding="utf-8"?><animated-vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:drawable="@drawable/ic_heart">      <target        android:name="clip"        android:animation="@animator/fill_heart" />  </animated-vector>In this step, we will define a static drawable object for vector graphics. Now create a new ic_heart.xml file in drawable directory and the following code.ic_heart.xmlic_heart.xml<?xml version="1.0" encoding="utf-8"?><vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:width="280dp"    android:height="280dp"    android:viewportWidth="56"    android:viewportHeight="56">      <path        android:name="empty"        android:pathData="@string/heart_empty_path"        android:fillColor="#219806" />      <clip-path        android:name="clip"        android:pathData="@string/heart_clip_hidden" />      <path        android:name="full"        android:pathData="@string/heart_full_path"        android:fillColor="#1A7A04" />  </vector>Now add the following code in the MainActivity.java file.MainActivity.javaMainActivity.javapackage org.geeksforgeeks.fillheart;  import android.app.Activity;import android.graphics.drawable.AnimatedVectorDrawable;import android.os.Bundle;import android.view.View;import android.widget.ImageView;  public class MainActivity extends Activity {      private ImageView imageView;    private AnimatedVectorDrawable emptyHeart;    private AnimatedVectorDrawable fillHeart;    private boolean full = false;      @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageView = findViewById(R.id.image_view);        emptyHeart            = (AnimatedVectorDrawable)                getDrawable(                    R.drawable.avd_heart_empty);        fillHeart            = (AnimatedVectorDrawable)                getDrawable(                    R.drawable.avd_heart_fill);    }      // This method help to animate our view.    public void animate(View view)    {        AnimatedVectorDrawable drawable            = full                  ? emptyHeart                  : fillHeart;        imageView.setImageDrawable(drawable);        drawable.start();        full = !full;    }}Now compile and run the Android app.
Create a new heart.xml file in values directory and add the following vector drawable path data and path commands:heart.xmlheart.xml<?xml version="1.0" encoding="utf-8"?><resources>    <!-- geometry -->    <string name="heart_empty_path">        M32.95, 19 C31.036, 19 29.199, 19.8828338 28,        21.2724796 C26.801, 19.8828338 24.964,         19 23.05, 19 C19.6565, 19 17, 21.6321526 17,        24.9945504 C17, 29.1089918 20.74, 32.4713896         26.405, 37.5667575 L28, 39 L29.595, 37.5667575 C35.26,        32.4713896 39, 29.1089918 39, 24.9945504 C39,        21.6321526 36.3435, 19 32.95, 19 L32.95,         19 Z M28.1155, 35.9536785 L28, 36.0572207 L27.8845,        35.9536785 C22.654, 31.2506812 19.2,        28.1444142 19.2, 24.9945504 C19.2, 22.8201635 20.8555,        21.1798365 23.05, 21.1798365 C24.744,         21.1798365 26.394, 22.2643052 26.9715, 23.7520436         L29.023, 23.7520436 C29.606, 22.2643052 31.256,        21.1798365 32.95, 21.1798365 C35.1445,         21.1798365 36.8, 22.8201635 36.8,        24.9945504 C36.8, 28.1444142 33.346,        31.2506812 28.1155, 35.9536785 L28.1155,        35.9536785 Z    </string>      <string name="heart_full_path">        M28, 39 L26.405, 37.5667575 C20.74,        32.4713896 17, 29.1089918 17,         24.9945504 C17, 21.6321526 19.6565,        19 23.05, 19 C24.964, 19 26.801, 19.8828338 28,        21.2724796 C29.199, 19.8828338 31.036, 19 32.95,        19 C36.3435, 19 39, 21.6321526 39, 24.9945504 C39,        29.1089918 35.26, 32.4713896 29.595,        37.5667575 L28, 39 L28, 39 Z    </string>      <string name="heart_clip_hidden">        M18 37 L38 37 L38 37 L18 37 Z    </string>      <string name="heart_clip_shown">        M0 0 L56 0 L56 56 L0 56 Z    </string></resources>
heart.xml
<?xml version="1.0" encoding="utf-8"?><resources>    <!-- geometry -->    <string name="heart_empty_path">        M32.95, 19 C31.036, 19 29.199, 19.8828338 28,        21.2724796 C26.801, 19.8828338 24.964,         19 23.05, 19 C19.6565, 19 17, 21.6321526 17,        24.9945504 C17, 29.1089918 20.74, 32.4713896         26.405, 37.5667575 L28, 39 L29.595, 37.5667575 C35.26,        32.4713896 39, 29.1089918 39, 24.9945504 C39,        21.6321526 36.3435, 19 32.95, 19 L32.95,         19 Z M28.1155, 35.9536785 L28, 36.0572207 L27.8845,        35.9536785 C22.654, 31.2506812 19.2,        28.1444142 19.2, 24.9945504 C19.2, 22.8201635 20.8555,        21.1798365 23.05, 21.1798365 C24.744,         21.1798365 26.394, 22.2643052 26.9715, 23.7520436         L29.023, 23.7520436 C29.606, 22.2643052 31.256,        21.1798365 32.95, 21.1798365 C35.1445,         21.1798365 36.8, 22.8201635 36.8,        24.9945504 C36.8, 28.1444142 33.346,        31.2506812 28.1155, 35.9536785 L28.1155,        35.9536785 Z    </string>      <string name="heart_full_path">        M28, 39 L26.405, 37.5667575 C20.74,        32.4713896 17, 29.1089918 17,         24.9945504 C17, 21.6321526 19.6565,        19 23.05, 19 C24.964, 19 26.801, 19.8828338 28,        21.2724796 C29.199, 19.8828338 31.036, 19 32.95,        19 C36.3435, 19 39, 21.6321526 39, 24.9945504 C39,        29.1089918 35.26, 32.4713896 29.595,        37.5667575 L28, 39 L28, 39 Z    </string>      <string name="heart_clip_hidden">        M18 37 L38 37 L38 37 L18 37 Z    </string>      <string name="heart_clip_shown">        M0 0 L56 0 L56 56 L0 56 Z    </string></resources>
Now create a new Android Resource Directory. Right-click on res folder and select Android Resource Directory. Make sure to select resource type as animator.Animators can change the physical properties of the objects. This means that if you move a View to a new location, the touch coordinates will be mapped at the new location without any other intervention.
Animators can change the physical properties of the objects. This means that if you move a View to a new location, the touch coordinates will be mapped at the new location without any other intervention.
Now create a new empty_heart.xml file in the animator directory. In this file, we mainly define the duration and animation type to the empty_heart.xml. This file is responsible for the animation when the user clicks on the filled heart icon.empty_heart.xmlempty_heart.xml<?xml version="1.0" encoding="utf-8"?><objectAnimator    xmlns:android="http://schemas.android.com/apk/res/android"    android:propertyName="pathData"    android:valueFrom="@string/heart_clip_shown"    android:valueTo="@string/heart_clip_hidden"    android:duration="600"    android:interpolator="@android:interpolator/fast_out_slow_in"    android:valueType="pathType" />
empty_heart.xml
<?xml version="1.0" encoding="utf-8"?><objectAnimator    xmlns:android="http://schemas.android.com/apk/res/android"    android:propertyName="pathData"    android:valueFrom="@string/heart_clip_shown"    android:valueTo="@string/heart_clip_hidden"    android:duration="600"    android:interpolator="@android:interpolator/fast_out_slow_in"    android:valueType="pathType" />
Now create a new fill_heart.xml file in animator directory. In this file, we mainly define the duration and animation type to the empty_heart.xml. This file is responsible for the animation when the user clicks on the empty heart icon.fill_heart.xmlfill_heart.xml<?xml version="1.0" encoding="utf-8"?><objectAnimator    xmlns:android="http://schemas.android.com/apk/res/android"    android:propertyName="pathData"    android:valueFrom="@string/heart_clip_hidden"    android:valueTo="@string/heart_clip_shown"    android:duration="800"    android:interpolator="@android:interpolator/fast_out_slow_in"    android:valueType="pathType" />In the next two steps, we will be creating AnimatedVectorDrawable for both empty heart and filled heart.
fill_heart.xml
<?xml version="1.0" encoding="utf-8"?><objectAnimator    xmlns:android="http://schemas.android.com/apk/res/android"    android:propertyName="pathData"    android:valueFrom="@string/heart_clip_hidden"    android:valueTo="@string/heart_clip_shown"    android:duration="800"    android:interpolator="@android:interpolator/fast_out_slow_in"    android:valueType="pathType" />
In the next two steps, we will be creating AnimatedVectorDrawable for both empty heart and filled heart.
Now create a new avd_heart_empty.xml file in the drawable directory and the following code.avd_heart_empty.xmlavd_heart_empty.xml<?xml version="1.0" encoding="utf-8"?><animated-vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:drawable="@drawable/ic_heart">      <target        android:name="clip"        android:animation="@animator/empty_heart" /></animated-vector>
avd_heart_empty.xml
<?xml version="1.0" encoding="utf-8"?><animated-vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:drawable="@drawable/ic_heart">      <target        android:name="clip"        android:animation="@animator/empty_heart" /></animated-vector>
Now create a new avd_heart_fill.xml file in drawable directory and the following code.avd_heart_fill.xmlavd_heart_fill.xml<?xml version="1.0" encoding="utf-8"?><animated-vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:drawable="@drawable/ic_heart">      <target        android:name="clip"        android:animation="@animator/fill_heart" />  </animated-vector>
avd_heart_fill.xml
<?xml version="1.0" encoding="utf-8"?><animated-vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:drawable="@drawable/ic_heart">      <target        android:name="clip"        android:animation="@animator/fill_heart" />  </animated-vector>
In this step, we will define a static drawable object for vector graphics. Now create a new ic_heart.xml file in drawable directory and the following code.ic_heart.xmlic_heart.xml<?xml version="1.0" encoding="utf-8"?><vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:width="280dp"    android:height="280dp"    android:viewportWidth="56"    android:viewportHeight="56">      <path        android:name="empty"        android:pathData="@string/heart_empty_path"        android:fillColor="#219806" />      <clip-path        android:name="clip"        android:pathData="@string/heart_clip_hidden" />      <path        android:name="full"        android:pathData="@string/heart_full_path"        android:fillColor="#1A7A04" />  </vector>
ic_heart.xml
<?xml version="1.0" encoding="utf-8"?><vector    xmlns:android="http://schemas.android.com/apk/res/android"    android:width="280dp"    android:height="280dp"    android:viewportWidth="56"    android:viewportHeight="56">      <path        android:name="empty"        android:pathData="@string/heart_empty_path"        android:fillColor="#219806" />      <clip-path        android:name="clip"        android:pathData="@string/heart_clip_hidden" />      <path        android:name="full"        android:pathData="@string/heart_full_path"        android:fillColor="#1A7A04" />  </vector>
Now add the following code in the MainActivity.java file.MainActivity.javaMainActivity.javapackage org.geeksforgeeks.fillheart;  import android.app.Activity;import android.graphics.drawable.AnimatedVectorDrawable;import android.os.Bundle;import android.view.View;import android.widget.ImageView;  public class MainActivity extends Activity {      private ImageView imageView;    private AnimatedVectorDrawable emptyHeart;    private AnimatedVectorDrawable fillHeart;    private boolean full = false;      @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageView = findViewById(R.id.image_view);        emptyHeart            = (AnimatedVectorDrawable)                getDrawable(                    R.drawable.avd_heart_empty);        fillHeart            = (AnimatedVectorDrawable)                getDrawable(                    R.drawable.avd_heart_fill);    }      // This method help to animate our view.    public void animate(View view)    {        AnimatedVectorDrawable drawable            = full                  ? emptyHeart                  : fillHeart;        imageView.setImageDrawable(drawable);        drawable.start();        full = !full;    }}
MainActivity.java
package org.geeksforgeeks.fillheart;  import android.app.Activity;import android.graphics.drawable.AnimatedVectorDrawable;import android.os.Bundle;import android.view.View;import android.widget.ImageView;  public class MainActivity extends Activity {      private ImageView imageView;    private AnimatedVectorDrawable emptyHeart;    private AnimatedVectorDrawable fillHeart;    private boolean full = false;      @Override    protected void onCreate(Bundle savedInstanceState)    {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageView = findViewById(R.id.image_view);        emptyHeart            = (AnimatedVectorDrawable)                getDrawable(                    R.drawable.avd_heart_empty);        fillHeart            = (AnimatedVectorDrawable)                getDrawable(                    R.drawable.avd_heart_fill);    }      // This method help to animate our view.    public void animate(View view)    {        AnimatedVectorDrawable drawable            = full                  ? emptyHeart                  : fillHeart;        imageView.setImageDrawable(drawable);        drawable.start();        full = !full;    }}
Now compile and run the Android app.
Output:
Media error: Format(s) not supported or source(s) not found
Reference:
AnimatedVectorDrawable
Vector Drawable
anikaseth98
Android-Animation
Android
Java
Java
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Broadcast Receiver in Android With Example
How to Create and Add Data to SQLite Database in Android?
Content Providers in Android with Example
Android RecyclerView in Kotlin
Flutter - Custom Bottom Navigation Bar
Arrays in Java
Split() String method in Java with examples
For-each loop in Java
Arrays.sort() in Java with examples
Reverse a string in Java