Android Compose Animation 기초
포스트
취소

Android Compose Animation 기초

안녕하세요. Narvis2 입니다.
이번 시간에는 Compose에서 Animation 을 사용하는 법에 대하여 알아보고자 합니다.
Animation에 대한 이해가 아직 부족하여 보다 자세히 알고 싶으시면 밑의 링크를 참고하세요.
Simple Animation
Deep Animation

🍎 1. animateColorAsState

  • UI 변경시의 Animation 사용

    animatedColorAsState(Color 값 넣기)

예제 animateColorAsState 를 사용하여 텍스트가 클릭된 상태면 빨간색, 아니라면 투명색 배경 지정 👇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Composable
fun Greeting(name: String) {
    var isSelected by remember { mutableStateOf(false) }

    val backgroundColor by animatedColorAsState(if (isSelected) Color.Red else Color.Transparent)

    Text(
        text = "안녕하세요 $name",
        modifier = Modifier
            .padding(24.dp)
            .backgroundColor(color = backgroundColor)
            .clickable(onClick = { isSelected = !isSelected })
    )
}

🍎 2. CompositionLocalProvider

  • alpha 값을 설정하기 위해 사용
  • 해당 블럭안에 있는 모든 하위 계층의 Composable 들에게 영향을 줌
  • LocalContentAlpha
    • Material Theme Level 에서 사용하는 Text, Icon 을 위한 alpha
    • 기본값 👉 1f, 투명도가 없이 보여짐

예제 👇

1
2
3
4
5
6
7
8
9
@Composable
fun PhotoGrapherCard() {
    Coloumn {
        Text(text = "안드로이드", fontWeight = FontWeight.Bold)
        CompositionLocalProvider(LocalContentAlpha provides ContentAlpha.medium) {
            Text(text = "3 minutes ago", style = MaterialTheme.typography.body2)
        }
    }
}

🍎 3. Animatable

  • animateTo 를 통해 값이 변경될 때 자동으로 값에 Animation 을 적용하는 값 홀더
  • 첫 번째 인자 initialValue 👉 초기 값
  • 두 번째 인자 typeConverter 👉 Animation 객체에 사용할 AnimationVector
  • 세 번째 인자 visibilityThreshold 👉 가시성 임계값
  • 내부 필드
    • value 👉 Animation 의 현재 값
    • targetValue 👉 현재 Animation 의 대상
    • animateTo 👉 targetValue 값을 향해 Animation 을 시작
      • animateTo 인자
        • targetValue, animationSpec, initialVelocity, block 이 있음
        • targetValue 👉 Animation 도달 값, 이 값이 작을 수록 Animation 이 작아짐
        • initialVelocity 👉 Animation 의 시작 값을 의미
        • block 👉 매 Animation 프레임 마다 호출됨

예제 Splash 화면👇 원이 커졌다가 작아지는 Animation, Animation 이 끝나면 다음 화면으로 진입

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Composable
fun WeatherSplashScreen(navController: NavController) {
    val scale = remember { Animatable(initialValue = 0f) }

    // LaunchedEffect : key1 이 바뀔때마다 블록내의 동작을 중지하고 다시 시작함
    // LaunchedEffect 에서 한 번만 실행되어야 하는 동작을 처리하기 위해 true를 넣음
    LaunchedEffect(key1 = true) {
        scale.animateTo(
            targetValue = 0.9f, // 이 값이 작을 수록 Animation 이 작아짐
            animationSpec = tween(
                durationMillis = 800, // 이 값이 커질수록 Animation 이 늦게 끝남
                easing = {
                    OvershootInterpolator(8f).getInterpolation(it)
                }
            )
        )

        // Animation 이 끝나고 2초 뒤 MainScreen 으로 이동
        delay(2000L)
        navController.navigate(WeatherScreens.MainScreen.name)
    }

    Surface(
        modifier = Modifier
            .padding(15.dp)
            .size(330.dp)
            .scale(scale.value),
        shape = CircleShape,
        color = Color.White,
        border = BorderStroke(width = 2.dp, color = Color.LightGray)
    ) {
        Column(
            modifier = Modifier.padding(1.dp),
            horizontalAlignment = Alignment.CenterHorizontally,
            verticalArrangement = Arrangement.Center
        ) {
            Image(
                painter = painterResource(id = R.drawable.sun),
                contentDescription = "sunny icon",
                contentScale = ContentScale.Fit,
                modifier = Modifier.size(95.dp)
            )
            Text(
                text = "Find the Sun?", style = MaterialTheme.typography.h5, color = Color.LightGray
            )
        }
    }
}
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.