
This is a button onClick animation made with Android Jetpack Compose. It has both a button and icon. When you click on them, the scale value will be changed with a nice animation. I’m using Animatable API to achieve this effect.
The Jetpack Compose button onClick function takes two parameters – animation duration and scale down value. The Animatable API offers the animationSpec parameter. I’m using tween here because I just need duration only.
When you tap on the icon or button, the size of the composables is changed. Inside the clickable block, I’m launching a new coroutine using the coroutineScope.launch() method. Next, the animateTo() method is called twice. This is because the scale value will become 0.9f in the first method and 1f in the second one.
For launching a coroutine, there is a rememberCoroutineScope() API in Jetpack Compose. It is useful because it remembers the state. There is a heart icon below the button. It is a “like animation” effect. You can find this in e-commerce apps where users can like the product. The like icon size is animated when you click on it.
You need to download the latest Android Studio to use the below code. The Jetpack Compose doesn’t work in the older versions.
Final output:
If the video isn’t working, watch it on the YouTube.
Helpful links to understand the code:
- Animations in Jetpack Compose Using Animatable
- State Management
- 3 Ways to Disable Ripple in Jetpack Compose
- What is Modifier in Jetpack Compose
Here are the Gradle files used in the project.
Here is the source code:
MainActivity.kt:
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.animation.core.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Favorite
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.launch
/*
You can use the following code for commercial purposes with some restrictions.
Read the full license here: https://semicolonspace.com/semicolonspace-license/
For more designs with source code, visit:
https://semicolonspace.com/jetpack-compose-samples/
*/
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
YourProjectNameTheme(darkTheme = false) {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
ButtonAnimation()
Spacer(modifier = Modifier.height(height = 36.dp))
HeartAnimation()
}
}
}
}
}
@Composable
fun ButtonAnimation(
animationDuration: Int = 100,
scaleDown: Float = 0.9f
) {
val interactionSource = MutableInteractionSource()
val coroutineScope = rememberCoroutineScope()
val scale = remember {
Animatable(1f)
}
Box(
modifier = Modifier
.scale(scale = scale.value)
.background(
color = Color(0xFF35898F),
shape = RoundedCornerShape(size = 12f)
)
.clickable(interactionSource = interactionSource, indication = null) {
coroutineScope.launch {
scale.animateTo(
scaleDown,
animationSpec = tween(animationDuration),
)
scale.animateTo(
1f,
animationSpec = tween(animationDuration),
)
}
}
) {
Text(
text = "Button Animation",
modifier = Modifier.padding(horizontal = 36.dp, vertical = 12.dp),
fontSize = 26.sp,
color = Color.White,
fontWeight = FontWeight.Medium
)
}
}
@Composable
fun HeartAnimation() {
val interactionSource = MutableInteractionSource()
val coroutineScope = rememberCoroutineScope()
var enabled by remember {
mutableStateOf(false)
}
val scale = remember {
Animatable(1f)
}
Icon(
imageVector = Icons.Outlined.Favorite,
contentDescription = "Like the product",
tint = if (enabled) Color.Red else Color.LightGray,
modifier = Modifier
.scale(scale = scale.value)
.size(size = 56.dp)
.clickable(
interactionSource = interactionSource,
indication = null
) {
enabled = !enabled
coroutineScope.launch {
scale.animateTo(
0.8f,
animationSpec = tween(100),
)
scale.animateTo(
1f,
animationSpec = tween(100),
)
}
}
)
}
Related: