はじめに
今回も前回に引き続きJetoackComposeでアニメーション関連の記事を書きたいと思います。
内容は 指で押すと凹むように縮み、離すとバウンドして元に戻る 物理的な押下感 を再現するボタンです。(前回までは押すと拡大されるViewを作成してアレンジしていましたが、今回は押すと小さくなるViewです。 ここから別の機能をつけてアレンジしていければと思っています。)
実装
@Composable
fun SpringButton(
modifier: Modifier = Modifier,
width: Float = 140f,
height: Float = 60f,
normalColor: Color = Color(0xFF2196F3),
pressedColor: Color = Color(0xFF1976D2),
text: String = "押してね",
onClick: () -> Unit = {}
) {
var pressed by remember { mutableStateOf(false) }
val haptic = LocalHapticFeedback.current
// scaleを押下状態でアニメーション
val scale by animateFloatAsState(
targetValue = if (pressed) 0.9f else 1f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessMedium
)
)
Box(
modifier = modifier
.size(width.dp, height.dp)
.graphicsLayer(
scaleX = scale,
scaleY = scale
)
.background(
color = if (pressed) pressedColor else normalColor,
shape = RoundedCornerShape(16.dp)
)
.pointerInput(Unit) {
detectTapGestures(
onPress = {
pressed = true
haptic.performHapticFeedback(HapticFeedbackType.TextHandleMove)
tryAwaitRelease() // 指を離すまで待機
pressed = false
onClick()
}
)
},
contentAlignment = Alignment.Center
) {
Text(
text = text,
color = Color.White,
fontSize = 18.sp,
fontWeight = FontWeight.Bold
)
}
}
軽く解説
- graphicsLayerで押すと凹む動きを作る
- animateFloatAsState + spring() でアニメーションでバウンドで戻る動きの表現
- if (pressed) pressedColor else normalColor で色変化
- LocalHapticFeedback.performHapticFeedback() で振動のフィードバック
- detectTapGestures(onPress) でタップ検知
