実践
@Composable
fun ScalableButton(
modifier: Modifier = Modifier,
onClick: () -> Unit,
content: @Composable () -> Unit
) {
// 押下状態を管理
var pressed by remember { mutableStateOf(false) }
// 拡大率をアニメーションで表す
val scale by animateFloatAsState(
targetValue = if (pressed) 1.1f else 1f,
animationSpec = spring(
dampingRatio = Spring.DampingRatioMediumBouncy,
stiffness = Spring.StiffnessLow
),
label = "scale"
)
Box(
modifier = modifier
.graphicsLayer(
scaleX = scale,
scaleY = scale
)
.pointerInteropFilter { event ->
when (event.action) {
MotionEvent.ACTION_DOWN -> pressed = true
MotionEvent.ACTION_UP,
MotionEvent.ACTION_CANCEL -> pressed = false
}
false // クリック処理を続けるためfalse
}
.clickable { onClick() },
contentAlignment = Alignment.Center
) {
content()
}
}
使う時↓
@Composable
fun ExampleScreen() {
ScalableButton(
onClick = { /* クリック時の処理 */ },
modifier = Modifier.size(120.dp)
) {
Box(
modifier = Modifier
.fillMaxSize()
.background(Color(0xFF2196F3), shape = CircleShape),
contentAlignment = Alignment.Center
) {
Text("押して!", color = Color.White, fontSize = 18.sp)
}
}
}
軽く解説
- animateFloatAsState や spring() を使用して自然で滑らかにアニメーションに見えるように
- pointerInteropFilter でACTION_DOWN(押下イベント)時とACTION_UP(離したイベント)時の操作
参考