Open In App

Create Bounce Animation on Touch in Android Jetpack Compose

Last Updated : 27 Jul, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

Prerequisites:

In this article, we will take a look at how to create a bounce animation when the user taps anything, further it can be extended as per the use of the App. Here’s a sample gif demonstrating the animation.

Step by Step Implementation

Step 1: Create a New Project (Or use it in the existing Compose project)

To create a new project in the Android Studio Canary version, refer to the article How to Create a new Project in the Android Studio Canary Version with Jetpack Compose.

Step 2: Working with the MainActivity.kt

Create an enum class that stores the states (Released / Pressed).

Kotlin




enum class BounceState { Pressed, Released }


 
Step 3: Adding Animation 

Create a composable function Bounce, add the following code 

Kotlin




var currentState: BounceState by remember { mutableStateOf(BounceState.Released) }
val transition = updateTransition(targetState = currentState, label = "animation")
 
val scale: Float by transition.animateFloat(
        transitionSpec = { spring(stiffness = 900f) }, label = ""
) { state ->
 
        // When the item is pressed , reduce
          // its size by 5% or make its size 0.95
          // of its original size
        // Change this value to see effect
        if (state == BounceState.Pressed) {
            0.95f
        } else {
            // When the item is released ,
              // make it of its original size
            1f
      }
}


Then use the pointerInputScope modifier to detect gestures and apply the animation, add the following code to the Bounce composable as well. 

Kotlin




// Basic compose Box Layout
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Column(modifier = Modifier
            .pointerInput(Unit) {
                detectTapGestures(onPress = {
 
                    // Set the currentState to Pressed
                      // to trigger Pressed animation
                    currentState = BounceState.Pressed
 
                    // Waits for the tap to release
                      // before returning the call
                    tryAwaitRelease()
 
                    // Set the currentState to Release
                      // to trigger Release animation
                    currentState = BounceState.Released
                })
            }) {
            Image(
                painter = painterResource(id = R.drawable.gfg),
                contentDescription = "gfg",
                modifier = Modifier.graphicsLayer {
                    scaleX = scale
                    scaleY = scale
              })
      }
}


 
And we are done. This is the final code for MainActivity.kt file. 

Kotlin




import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.Transition
import androidx.compose.animation.core.animateFloat
import androidx.compose.animation.core.spring
import androidx.compose.animation.core.updateTransition
import androidx.compose.foundation.Image
import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
import com.shaun.bounceanimation.ui.theme.BounceAnimationTheme
 
class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            BounceAnimationTheme {
                Surface(color = MaterialTheme.colors.background) {
                    Bounce()
                }
            }
        }
    }
}
 
enum class BounceState { Pressed, Released }
 
@Preview(showBackground = true)
@Composable
fun Bounce() {
    var currentState: BounceState by remember { mutableStateOf(BounceState.Released) }
    val transition = updateTransition(targetState = currentState, label = "animation")
    val scale: Float by transition.animateFloat(
        transitionSpec = { spring(stiffness = 900f) }, label = ""
    ) { state ->
 
        // When the item is pressed ,reduce its size
          // by 5% or make its size 0.95 of its original size
        // Change this value to see effect
        if (state == BounceState.Pressed) {
            0.95f
        } else {
            // When the item is released ,
             // make it of its original size
            1f
        }
    }
 
// Basic compose Box Layout
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
 
Column(modifier = Modifier
            .pointerInput(Unit) {
                detectTapGestures(onPress = {
 
                    // Set the currentState to Pressed
                      // to trigger Pressed animation
                    currentState = BounceState.Pressed
 
                    // Waits for the tap to release
                      // before returning the call
                    tryAwaitRelease()
 
                    // Set the currentState to Release
                      // to trigger Release animation
                    currentState = BounceState.Released
                })
            }) {
            Image(
                painter = painterResource(id = R.drawable.gfg),
                contentDescription = "gfg",
                modifier = Modifier.graphicsLayer {
                    scaleX = scale
                    scaleY = scale
              })
        }
    }
}


Output:

Get the complete project from here.

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads