안드로이드/Compose

[Android] Compose - Animation

damon-911 2024. 5. 25. 18:10

Animation

Animation사용자 경험을 향상시키고, 앱의 인터페이스를 더 직관적이고 반응적으로 만드는 데 중요한 역할을 합니다.

 

Compose의 애니메이션  |  Jetpack Compose  |  Android Developers

Compose의 애니메이션은 사용하기 쉬우며 앱에서 훌륭한 상호작용을 제공합니다.

developer.android.com

 

나타나거나 사라지는 애니메이션

AnimatedVisibility 함수를 사용하면 visible 속성에 넣은 값에 따라 컴포저블을 숨기거나 표시할 수 있습니다.

 

애니메이션 수정자 및 컴포저블  |  Jetpack Compose  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 애니메이션 수정자 및 컴포저블 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Compose에는 일반적인

developer.android.com

@Composable
fun AnimatedVisibility(
    visible: Boolean,
    modifier: Modifier = Modifier,
    enter: EnterTransition = fadeIn() + expandVertically(),
    exit: ExitTransition = fadeOut() + shrinkVertically(),
    label: String = "AnimatedVisibility",
    content: @Composable AnimatedVisibilityScope.() -> Unit
): Unit
  • visible : visible 설정
  • modifier : 애니메이션에 적용할 modifier 설정
  • enter : 표시되는 애니메이션에 사용할 Transition 설정 ('+'으로 결합 가능)
  • exit : 소멸되는 애니메이션에 사용할 Transition 설정 ('+'으로 결합 가능)
  • label : 해당 함수에 붙일 label 설정
  • content : 이를 대상으로 하는 content 설정

 

EnterTransition 및 ExitTransition 예시

EnterTransition ExitTransition
fadeIn
페이드 인 애니메이션
fadeOut
페이드 아웃 애니메이션
slideIn
슬라이드 인 애니메이션
slideOut
슬라이드 아웃 애니메이션
slideInHorizontally
가로 슬라이드 인 애니메이션
slideOutHorizontally
가로 슬라이드 아웃 애니메이션
slideInVertically
세로 슬라이드 인 애니메이션
slideOutVertically
세로 슬라이드 아웃 애니메이션
scaleIn
스케일 인 애니메이션
scaleOut
스케일 아웃 애니메이션
expandIn
확장 애니메이션
shrinkOut
축소 애니메이션
expandHorizontally
가로 확장 애니메이션
shrinkHorizontally
가로 축소 애니메이션
expandVertically
세로 확장 애니메이션
shrinkVertically
세로 축소 애니메이션

 

AnimatedVisibility 사용 예시

@Composable
fun AnimationExample() {
    var helloWorldVisible by remember { mutableStateOf(true) }
    
    Column(
        modifier = Modifier
            .fillMaxSize()
    ) {
        AnimatedVisibility(
            visible = helloWorldVisible,
            enter = expandVertically() + slideInHorizontally(),
            exit = slideOutHorizontally()
        ) {
            Text(text = "Hello World!")
        }

        RadioButtonWithText(text = "Hello World 보이기", selected = helloWorldVisible) {
            helloWorldVisible = true
        }
           
        RadioButtonWithText(text = "Hello World 감추기", selected = !helloWorldVisible) {
            helloWorldVisible = false
        }
        
        ...
    }
}

 

배경색 또는 알파값에 애니메이션 적용

animate(...)AsState 함수를 사용하면 설정해놓은 targetValue가 변경됨에 따라 상태가 달라지는 애니메이션을 만들 수 있습니다.

또한, updateTransition 함수를 통해서도 Transition인스턴스를 만들고 기억하며 상태를 업데이트할 수 있습니다.

 

가치 기반 애니메이션  |  Jetpack Compose  |  Android Developers

이 페이지는 Cloud Translation API를 통해 번역되었습니다. 가치 기반 애니메이션 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. animate*AsState를 사용하여 단일 값

developer.android.com

@Composable
fun <T> updateTransition(
    targetState: T,
    label: String? = null
): Transition<T>
@Composable
fun animateColorAsState(
    targetValue: Color,
    animationSpec: AnimationSpec<Color> = colorDefaultSpring,
    label: String = "ColorAnimation",
    finishedListener: ((Color) -> Unit)? = null
): State<Color>

@Composable
inline fun <S> Transition<S>.animateColor(
    noinline transitionSpec:
    @Composable Transition.Segment<S>.() -> FiniteAnimationSpec<Color> = { spring() },
    label: String = "ColorAnimation",
    targetValueByState: @Composable() (state: S) -> Color
): State<Color>
@Composable
fun animateFloatAsState(
    targetValue: Float,
    animationSpec: AnimationSpec<Float> = defaultAnimation,
    visibilityThreshold: Float = 0.01f,
    label: String = "FloatAnimation",
    finishedListener: ((Float) -> Unit)? = null
): State<Float>

@Composable
inline fun <S> Transition<S>.animateFloat(
    noinline transitionSpec:
    @Composable Transition.Segment<S>.() -> FiniteAnimationSpec<Float> = { spring() },
    label: String = "FloatAnimation",
    targetValueByState: @Composable (state: S) -> Float
): State<Float>

 

animate(...)AsState 함수 사용 예시

  • "흰색" 라디오 버튼이 선택되어 있는 경우 : 흰색 배경색 + 알파값이 1f
  • "노란색" 라디오 버튼이 선택되어 있는 경우 : 노란색 배경색 + 알파값이 0.5f
@Composable
fun AnimationExample() {
    // animateColorAsState를 통해 isYellow 상태에 따라 color 설정
    val color by animateColorAsState(
        targetValue = if (isYellow) Color.Yellow else Color.White, label = "Color"
    )

    // animateFloatAsState를 통해 isYellow 상태에 따라 alpha 설정
    val alpha by animateFloatAsState(
        targetValue = if (isYellow) 0.5f else 1.0f, label = "Alpha"
    )

    ...

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .background(color)
            .alpha(alpha)
            .padding(16.dp)
    ) {
        Text(text = "배경색 설정")
        
        RadioButtonWithText(text = "흰색", selected = !isYellow) {
            isYellow = false
        }
        
        RadioButtonWithText(text = "노란색", selected = isYellow) {
            isYellow = true
        }
        
        ...
    }
}

@Composable
fun RadioButtonWithText(
    text: String,
    color: Color = Color.Black,
    selected: Boolean,
    onClick: () -> Unit
) {
    Row(
        modifier = Modifier.selectable(
            selected = selected,
            onClick = onClick
        ),
        verticalAlignment = Alignment.CenterVertically
    ) {
        RadioButton(selected = selected, onClick = onClick)
        Text(text = text, color = color)
    }
}

 

updateTransition 함수 사용 예시

  • "일반 모드" 라디오 버튼이 선택되어 있는 경우 : 흰색 배경색 + 검정색 글씨색 + 알파값이 0.5f
  • "다크 모드" 라디오 버튼이 선택되어 있는 경우 : 노란색 배경색 + 흰색 글씨색 + 알파값이 1f
@Composable
fun AnimationExample() {
    var isDarkMode by remember { mutableStateOf(false) }

    // updateTransition을 통해 isDarkMode 상태 관리
    val transition = updateTransition(
        targetState = isDarkMode,
        label = "Dark Mode Transition"
    )
    // transition에 대해 animateColor를 호출해 배경색 설정
    val backgroundColor by transition.animateColor(label = "Dark Mode Background Color") { state ->
        when (state) {
            false -> Color.White
            true -> Color.Black
        }
    }
    // transition에 대해 animateColor를 호출해 글자색 설정
    val textColor by transition.animateColor(label = "Dark Mode Text Color") { state ->
        when (state) {
            false -> Color.Black
            true -> Color.White
        }
    }
    // transition에 대해 animateFloat을 호출해 alpha 값 설정
    val alphaValue by transition.animateFloat(label = "Dark Mode Alpha Value") { state ->
        when (state) {
            false -> 0.5f
            true -> 1f
        }
    }

    Column(
        modifier = Modifier
            .fillMaxWidth()
            .background(backgroundColor)
            .alpha(alphaValue)
            .padding(16.dp)
    ) {
        Text(text = "다크 모드 설정", color = textColor)

        RadioButtonWithText(
            text = "일반 모드",
            color = textColor,
            selected = !isDarkMode
        ) {
            isDarkMode = false
        }
            
        RadioButtonWithText(
            text = "다크 모드",
            color = textColor,
            selected = isDarkMode
        ) {
            isDarkMode = true
        }
        
        ...
    }
}

@Composable
fun RadioButtonWithText(
    text: String,
    color: Color = Color.Black,
    selected: Boolean,
    onClick: () -> Unit
) {
    Row(
        modifier = Modifier.selectable(
            selected = selected,
            onClick = onClick
        ),
        verticalAlignment = Alignment.CenterVertically
    ) {
        RadioButton(selected = selected, onClick = onClick)
        Text(text = text, color = color)
    }
}

728x90
반응형