Use ButtonGroup for even more juicy button morph animations

This commit is contained in:
Nishant Mishra
2025-07-01 10:21:56 +05:30
parent eb8cb61c96
commit 9d087ce0d2

View File

@@ -5,10 +5,10 @@ import androidx.compose.animation.animateColorAsState
import androidx.compose.animation.slideInVertically import androidx.compose.animation.slideInVertically
import androidx.compose.animation.slideOutVertically import androidx.compose.animation.slideOutVertically
import androidx.compose.animation.togetherWith import androidx.compose.animation.togetherWith
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.aspectRatio import androidx.compose.foundation.layout.aspectRatio
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
@@ -18,6 +18,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn import androidx.compose.foundation.layout.widthIn
import androidx.compose.material3.ButtonGroup
import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.CircularWavyProgressIndicator import androidx.compose.material3.CircularWavyProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExperimentalMaterial3Api
@@ -35,6 +36,7 @@ import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.StrokeCap import androidx.compose.ui.graphics.StrokeCap
@@ -210,21 +212,34 @@ fun TimerScreen(
maxLines = 1 maxLines = 1
) )
} }
Row( val interactionSources = remember { List(2) { MutableInteractionSource() } }
horizontalArrangement = Arrangement.spacedBy(8.dp), ButtonGroup(
overflowIndicator = {},
modifier = Modifier.padding(16.dp) modifier = Modifier.padding(16.dp)
) { ) {
customItem(
{
FilledTonalIconButton( FilledTonalIconButton(
onClick = resetTimer, onClick = resetTimer,
colors = IconButtonDefaults.filledTonalIconButtonColors(containerColor = colorContainer), colors = IconButtonDefaults.filledTonalIconButtonColors(
containerColor = colorContainer
),
shapes = IconButtonDefaults.shapes(), shapes = IconButtonDefaults.shapes(),
modifier = Modifier.size(96.dp) interactionSource = interactionSources[0],
modifier = Modifier
.size(96.dp)
.animateWidth(interactionSources[0])
) { ) {
Icon( Icon(
painterResource(R.drawable.restart_large), painterResource(R.drawable.restart_large),
contentDescription = "Restart" contentDescription = "Restart"
) )
} }
},
{}
)
customItem(
{
FilledIconToggleButton( FilledIconToggleButton(
onCheckedChange = { toggleTimer() }, onCheckedChange = { toggleTimer() },
checked = uiState.timerRunning, checked = uiState.timerRunning,
@@ -233,7 +248,10 @@ fun TimerScreen(
checkedContentColor = onColor checkedContentColor = onColor
), ),
shapes = IconButtonDefaults.toggleableShapes(), shapes = IconButtonDefaults.toggleableShapes(),
modifier = Modifier.size(width = 128.dp, height = 96.dp) interactionSource = interactionSources[1],
modifier = Modifier
.size(width = 128.dp, height = 96.dp)
.animateWidth(interactionSources[1])
) { ) {
if (uiState.timerRunning) { if (uiState.timerRunning) {
Icon( Icon(
@@ -247,6 +265,9 @@ fun TimerScreen(
) )
} }
} }
},
{}
)
} }
} }
@@ -277,7 +298,11 @@ fun TimerScreen(
} }
} }
@Preview(showSystemUi = true) @Preview(
widthDp = 384,
heightDp = 832,
showSystemUi = true
)
@Composable @Composable
fun TimerScreenPreview() { fun TimerScreenPreview() {
val uiState = UiState( val uiState = UiState(