Circular Reveal Animation in Android - GeeksforGeeks

23 Feb, 2021
Animations in Android play an important role in the user experience. This makes the user focus on the main content, which they want. And also helps in user interactivity. Animations communicate with the user to really get engaged in application usage. So in this article, one of the animations in android which is the most popular one, Circular reveal animation is discussed. Have a look at the following image to get an idea of how the circular animation looks like. Note that we are going to implement this project using the Kotlin language. 
Step 1: Create an empty activity project
Create an empty activity Android Studio Project. Or refer to Android | How to Create/Start a New Project in Android Studio? to know how to create an empty activity Android Studio project. Note that select Kotlin as the programming language.
Step 2: Working with the activity_main.xml file
To implement the application’s main layout in which includes only a single button, which when clicked on it triggers the Circular reveal animation.
To implement the UI invoke the following code inside the activity_main.xml file.
XML
<?xml version="1.0" encoding="utf-8"?><RelativeLayout     xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:id="@+id/mainLayout"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:fitsSystemWindows="true"    tools:context=".MainActivity"    tools:ignore="HardcodedText">      <TextView        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginTop="16dp"        android:gravity="center"        android:text="GeeksforGeeks"        android:textColor="@color/green_500"        android:textSize="24sp"        android:textStyle="bold" />      <!--The layout which is invisible initially-->    <LinearLayout        android:id="@+id/revealLayout"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:background="@color/green_200"        android:gravity="center"        android:orientation="vertical"        android:visibility="gone">          <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:backgroundTint="@android:color/white"            android:text="LEARN PROGRAMMING"            android:textColor="@android:color/black" />          <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:backgroundTint="@android:color/white"            android:text="CONTRIBUTE"            android:textColor="@android:color/black" />          <Button            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:backgroundTint="@android:color/white"            android:text="VISIT WEBSITE"            android:textColor="@android:color/black" />      </LinearLayout>      <!--The Fab to toggle the visibility of circular reveal animation-->    <com.google.android.material.floatingactionbutton.FloatingActionButton        android:id="@+id/fab"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentEnd="true"        android:layout_alignParentBottom="true"        android:layout_gravity="bottom|end"        android:layout_marginEnd="16dp"        android:layout_marginBottom="16dp"        app:srcCompat="@drawable/ic_add" />  </RelativeLayout>
Output UI:
Step 3: Working with the MainActivity.kt file
Firstly, the code is for the circular reveal animation from the right bottom of the screen.
Invoke the following code and refer to its output for better understanding, the comments are added for better understanding.
Kotlin
import android.animation.Animatorimport android.annotation.SuppressLintimport android.content.res.ColorStateListimport android.os.Buildimport android.os.Bundleimport android.view.Viewimport android.view.ViewAnimationUtilsimport androidx.annotation.RequiresApiimport androidx.appcompat.app.AppCompatActivityimport androidx.core.content.res.ResourcesCompatimport com.google.android.material.floatingactionbutton.FloatingActionButtonimport kotlin.math.hypotimport kotlin.math.max  class MainActivity : AppCompatActivity() {      private lateinit var mRevealLayout: View    private lateinit var mFab: FloatingActionButton      // boolean variable to check whether the      // reveal layout is visible or not    private var isRevealed = false      @RequiresApi(Build.VERSION_CODES.M)    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)          mRevealLayout = findViewById(R.id.revealLayout)        mFab = findViewById(R.id.fab)          // initially the color of the FAB should be green        mFab.backgroundTintList = ColorStateList.valueOf(                ResourcesCompat.getColor(                        resources,                        R.color.green_500,                        null                )        )          // upon clicking the FAB the reveal should be           // toggled according to the boolean value        mFab.setOnClickListener {            revealLayoutFun()        }    }      // this function is triggered when       // the FAB is clicked    @RequiresApi(Build.VERSION_CODES.M)    @SuppressLint("ResourceAsColor")    private fun revealLayoutFun() {          // based on the boolean value the           // reveal layout should be toggled        if (!isRevealed) {              // get the right and bottom side               // lengths of the reveal layout            val x: Int = mRevealLayout.right            val y: Int = mRevealLayout.bottom              // here the starting radius of the reveal               // layout is 0 when it is not visible            val startRadius = 0              // make the end radius should match              // the while parent view            val endRadius = hypot(                    mRevealLayout.width.toDouble(),                    mRevealLayout.height.toDouble()            ).toInt()              // and set the background tint of the FAB to white               // color so that it can be visible            mFab.backgroundTintList = ColorStateList.valueOf(                    ResourcesCompat.getColor(                            resources,                            R.color.white,                            null                    )            )            // now set the icon as close for the FAB            mFab.setImageResource(R.drawable.ic_close)              // create the instance of the ViewAnimationUtils to               // initiate the circular reveal animation            val anim = ViewAnimationUtils.createCircularReveal(                    mRevealLayout,                    x,                    y,                    startRadius.toFloat(),                    endRadius.toFloat()            )              // make the invisible reveal layout to visible               // so that upon revealing it can be visible to user            mRevealLayout.visibility = View.VISIBLE            // now start the reveal animation            anim.start()              // set the boolean value to true as the reveal              // layout is visible to the user            isRevealed = true          } else {              // get the right and bottom side lengths               // of the reveal layout            val x: Int = mRevealLayout.right            val y: Int = mRevealLayout.bottom              // here the starting radius of the reveal layout is its full width            val startRadius: Int = max(mRevealLayout.width, mRevealLayout.height)              // and the end radius should be zero               // at this point because the layout should be closed            val endRadius = 0              // now set the background tint of the FAB to green              // so that it can be visible to the user            mFab.backgroundTintList = ColorStateList.valueOf(                    ResourcesCompat.getColor(                            resources,                            R.color.green_500,                            null                    )            )              // now again set the icon of the FAB to plus            mFab.setImageResource(R.drawable.ic_add)              // create the instance of the ViewAnimationUtils to               // initiate the circular reveal animation            val anim = ViewAnimationUtils.createCircularReveal(                    mRevealLayout,                    x,                    y,                    startRadius.toFloat(),                    endRadius.toFloat()            )              // now as soon as the animation is ending, the reveal               // layout should also be closed            anim.addListener(object : Animator.AnimatorListener {                override fun onAnimationStart(animator: Animator) {}                override fun onAnimationEnd(animator: Animator) {                    mRevealLayout.visibility = View.GONE                }                  override fun onAnimationCancel(animator: Animator) {}                override fun onAnimationRepeat(animator: Animator) {}            })              // start the closing animation            anim.start()              // set the boolean variable to false              // as the reveal layout is invisible            isRevealed = false        }    }}
Output:
Note: The layout of the application remains same only the code from the MainActivity.kt file are changed.
Invoke the following code inside the MainActivity.kt file to reveal the same layout from the center of the screen.
Kotlin
import android.animation.Animatorimport android.annotation.SuppressLintimport android.content.res.ColorStateListimport android.os.Buildimport android.os.Bundleimport android.view.Viewimport android.view.ViewAnimationUtilsimport androidx.annotation.RequiresApiimport androidx.appcompat.app.AppCompatActivityimport androidx.core.content.res.ResourcesCompatimport com.google.android.material.floatingactionbutton.FloatingActionButtonimport kotlin.math.hypotimport kotlin.math.max  class MainActivity : AppCompatActivity() {      private lateinit var mRevealLayout: View    private lateinit var mFab: FloatingActionButton      // boolean variable to check whether      // the reveal layout is visible or not    private var isRevealed = false      @RequiresApi(Build.VERSION_CODES.M)    override fun onCreate(savedInstanceState: Bundle?) {        super.onCreate(savedInstanceState)        setContentView(R.layout.activity_main)          mRevealLayout = findViewById(R.id.revealLayout)        mFab = findViewById(R.id.fab)          // initially the color of the FAB should be green        mFab.backgroundTintList = ColorStateList.valueOf(                ResourcesCompat.getColor(                        resources,                        R.color.green_500,                        null                )        )          // upon clicking the FAB the reveal should          // be toggled according to the boolean value        mFab.setOnClickListener {            revealLayoutFun()        }    }      // this function is triggered when      // the FAB is clicked    @RequiresApi(Build.VERSION_CODES.M)    @SuppressLint("ResourceAsColor")    private fun revealLayoutFun() {          // based on the boolean value the           // reveal layout should be toggled        if (!isRevealed) {              // get the right and bottom side               // lengths of the reveal layout            val x: Int = mRevealLayout.right / 2            val y: Int = mRevealLayout.bottom / 2              // here the starting radius of the reveal              // layout is 0 when it is not visible            val startRadius = 0              // make the end radius should              // match the while parent view            val endRadius = hypot(                    mRevealLayout.width.toDouble(),                    mRevealLayout.height.toDouble()            ).toInt()              // and set the background tint of the FAB to white              // color so that it can be visible            mFab.backgroundTintList = ColorStateList.valueOf(                    ResourcesCompat.getColor(                            resources,                            R.color.white,                            null                    )            )            // now set the icon as close for the FAB            mFab.setImageResource(R.drawable.ic_close)              // create the instance of the ViewAnimationUtils to               // initiate the circular reveal animation            val anim = ViewAnimationUtils.createCircularReveal(                    mRevealLayout,                    x,                    y,                    startRadius.toFloat(),                    endRadius.toFloat()            )              // make the invisible reveal layout to visible               // so that upon revealing it can be visible to user            mRevealLayout.visibility = View.VISIBLE            // now start the reveal animation            anim.start()              // set the boolean value to true as the reveal               // layout is visible to the user            isRevealed = true          } else {              // get the right and bottom side lengths              // of the reveal layout            val x: Int = mRevealLayout.right / 2            val y: Int = mRevealLayout.bottom / 2              // here the starting radius of the reveal layout is its full width            val startRadius: Int = max(mRevealLayout.width, mRevealLayout.height)              // and the end radius should be zero at this               // point because the layout should be closed            val endRadius = 0              // now set the background tint of the FAB to green              // so that it can be visible to the user            mFab.backgroundTintList = ColorStateList.valueOf(                    ResourcesCompat.getColor(                            resources,                            R.color.green_500,                            null                    )            )              // now again set the icon of the FAB to plus            mFab.setImageResource(R.drawable.ic_add)              // create the instance of the ViewAnimationUtils               // to initiate the circular reveal animation            val anim = ViewAnimationUtils.createCircularReveal(                    mRevealLayout,                    x,                    y,                    startRadius.toFloat(),                    endRadius.toFloat()            )              // now as soon as the animation is ending, the reveal               // layout should also be closed            anim.addListener(object : Animator.AnimatorListener {                override fun onAnimationStart(animator: Animator) {}                override fun onAnimationEnd(animator: Animator) {                    mRevealLayout.visibility = View.GONE                }                  override fun onAnimationCancel(animator: Animator) {}                override fun onAnimationRepeat(animator: Animator) {}            })              // start the closing animation            anim.start()              // set the boolean variable to false              // as the reveal layout is invisible            isRevealed = false        }    }}
Output:
Android-Animation
Technical Scripter 2020
Android
Kotlin
Technical Scripter
Android
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Comments
Old Comments
Retrofit with Kotlin Coroutine in Android
Android Listview in Java with Example
How to Read Data from SQLite Database in Android?
Flutter - Custom Bottom Navigation Bar
How to Change the Background Color After Clicking the Button in Android?
Android UI Layouts
Kotlin Array
Retrofit with Kotlin Coroutine in Android
Kotlin Setters and Getters
MVP (Model View Presenter) Architecture Pattern in Android with Example