Search code examples
androidandroid-jetpack-composeandroid-compose-button

Scaling Button Animation in Jetpack Compose


I want to build this awesome button animation pressed from the AirBnB App with Jetpack Compose 1

Unfortunately, the Animation/Transition API was changed recently and there's almost no documentation for it. Can someone help me get the right approach to implement this button press animation?

Edit Based on @Amirhosein answer I have developed a button that looks almost exactly like the Airbnb example

Code:

@Composable
fun AnimatedButton() {
    val boxHeight = animatedFloat(initVal = 50f)
    val relBoxWidth = animatedFloat(initVal = 1.0f)
    val fontSize = animatedFloat(initVal = 16f)

    fun animateDimensions() {
        boxHeight.animateTo(45f)
        relBoxWidth.animateTo(0.95f)
       // fontSize.animateTo(14f)
    }

    fun reverseAnimation() {
        boxHeight.animateTo(50f)
        relBoxWidth.animateTo(1.0f)
        //fontSize.animateTo(16f)
    }

        Box(
        modifier = Modifier
            .height(boxHeight.value.dp)
            .fillMaxWidth(fraction = relBoxWidth.value)

            .clip(RoundedCornerShape(8.dp))
            .background(Color.Black)
            .clickable { }
            .pressIndicatorGestureFilter(
                onStart = {
                    animateDimensions()
                },
                onStop = {
                    reverseAnimation()
                },
                onCancel = {
                    reverseAnimation()
                }
            ),
        contentAlignment = Alignment.Center
    ) {
        Text(text = "Explore Airbnb", fontSize = fontSize.value.sp, color = Color.White)
    }
}

Video:

2

Unfortunately, I cannot figure out how to animate the text correctly as It looks very bad currently


Solution

  • Are you looking for something like this?

    @Composable
    fun AnimatedButton() {
        val selected = remember { mutableStateOf(false) }
        val scale = animateFloatAsState(if (selected.value) 2f else 1f)
    
        Column(
            Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Button(
                onClick = {  },
                modifier = Modifier
                    .scale(scale.value)
                    .height(40.dp)
                    .width(200.dp)
                    .pointerInteropFilter {
                        when (it.action) {
                            MotionEvent.ACTION_DOWN -> {
                                selected.value = true }
    
                            MotionEvent.ACTION_UP  -> {
                               selected.value = false }
                        }
                        true
                    }
            ) {
                Text(text = "Explore Airbnb", fontSize = 15.sp, color = Color.White)
            }
        }
    }