728x90
안녕하세요
오늘은 안드로이드의 Jetpack Compose 에서 제공하는 애니메이션 API 를 사용해보겠습니다.
Jetpack Compose 에서는 애니메이션을 쉽게 구현할 수 있는 api 를 여러가지 제공합니다
오늘은 특정 값에 따라 막대 그래프의 높이가 변하도록 애니메이션을 적용해보겠습니다
사용자에게 1부터 "점수 입력 (0-100)" 칸에 1부터 100까지의 숫자 중 아무 숫자를 입력한 후 적용하기 버튼을 누릅니다.
버튼을 누르면 입력 받은 숫자값(score) 만큼 그래프가 증가, 감소합니다.
@Composable
fun GraphDemo() {
var score by remember { mutableStateOf(0f) }
var input by remember { mutableStateOf("") }
Column(modifier = Modifier.fillMaxSize().padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally) {
RisingBarGraph(score)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = input,
onValueChange = {
input = it
score = it.toFloatOrNull() ?: 0f
},
label = { Text("점수 입력 (0-100)") },
modifier = Modifier.padding(16.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = {
score = input.toFloatOrNull()?.coerceIn(0f, 100f) ?: 0f
}) {
Text("점수 반영하기", fontSize = 18.sp)
}
}
}
입력받은 숫자 (score) 를 기준으로 그래프의 최대 높이인 200f 에 맞추어서 비례적으로 계산이 됩니다.
계산된만큼 Canvas 위에 그래프가 그려집니다
animateTo 사용: animateTo 함수는 현재 높이에서 목표 높이 (targetHeight)로 부드럽게 애니메이션합니다.
애니메이션 스펙은 tween(durationMillis = 1500)으로 지정되어 있으며, 이는 1.5초 동안 목표 값으로 부드럽게 이동하도록 설정합니다.
@Composable
fun RisingBarGraph(score: Float) {
val animatedHeight = remember { Animatable(0f) }
LaunchedEffect(score) {
val maxHeight = 200f // Max height for 100 points
val targetHeight = (score / 100) * maxHeight
animatedHeight.animateTo(
targetValue = targetHeight,
animationSpec = tween(durationMillis = 1500)
)
}
Canvas(modifier = Modifier.fillMaxWidth().height(200.dp).padding(16.dp)) {
val canvasWidth = size.width
val canvasHeight = size.height
drawRoundRect(
color = Color.Blue,
topLeft = androidx.compose.ui.geometry.Offset(x = 0f, y = canvasHeight - animatedHeight.value),
size = Size(width = canvasWidth, height = animatedHeight.value),
cornerRadius = CornerRadius(8.dp.toPx(), 8.dp.toPx())
)
}
}
class MainActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
GraphDemo()
}
}
}
@Composable
fun RisingBarGraph(score: Float) {
val animatedHeight = remember { Animatable(0f) }
LaunchedEffect(score) {
val maxHeight = 200f // Max height for 100 points
val targetHeight = (score / 100) * maxHeight
animatedHeight.animateTo(
targetValue = targetHeight,
animationSpec = tween(durationMillis = 1500)
)
}
Canvas(modifier = Modifier.fillMaxWidth().height(200.dp).padding(16.dp)) {
val canvasWidth = size.width
val canvasHeight = size.height
drawRoundRect(
color = Color.Blue,
topLeft = androidx.compose.ui.geometry.Offset(x = 0f, y = canvasHeight - animatedHeight.value),
size = Size(width = canvasWidth, height = animatedHeight.value),
cornerRadius = CornerRadius(8.dp.toPx(), 8.dp.toPx())
)
}
}
@Composable
fun GraphDemo() {
var score by remember { mutableStateOf(0f) }
var input by remember { mutableStateOf("") }
Column(modifier = Modifier.fillMaxSize().padding(16.dp), horizontalAlignment = Alignment.CenterHorizontally) {
RisingBarGraph(score)
Spacer(modifier = Modifier.height(16.dp))
OutlinedTextField(
value = input,
onValueChange = {
input = it
score = it.toFloatOrNull() ?: 0f
},
label = { Text("점수 입력 (0-100)") },
modifier = Modifier.padding(16.dp)
)
Spacer(modifier = Modifier.height(16.dp))
Button(onClick = {
score = input.toFloatOrNull()?.coerceIn(0f, 100f) ?: 0f
}) {
Text("점수 반영하기", fontSize = 18.sp)
}
}
}
@Composable
@Preview(showBackground = true)
fun GraphDemoPreview() {
GraphDemo()
}
전체 코드입니다.
감사합니다
'안드로이드 코틀린' 카테고리의 다른 글
[Kotlin][Android] Jetpack Compose로 아이템 Drag & Drop 구현하기 (0) | 2024.12.15 |
---|---|
[Kotlin][Android] 슬라이더와 애니메이션을 활용한 RGB 색상 조합기 만들기 (4) | 2024.12.09 |
[Kotlin][Android] Jetpack Compose 텍스트 작성 중인 상태에 대해 사용자에게 알리기 (0) | 2024.11.27 |
[Kotlin][Android] 문자열 형식 체크하기 (0) | 2024.11.23 |
[Kotlin][Android] Jetpack Compose 아이템 일괄 삭제하기 (0) | 2024.11.21 |