[Jetpack Compose] AnimatedVisibility 컴포저블

유민국·2024년 10월 20일

AnimatedVisibility

visible:Boolean값에 따라 content를 애니메이션 처리하는 컴포저블이다

애니메이션이 끝난 후에는 content가 트리에서 제거되기때문에 상태 변화를 관찰하거나 추가 작업(ex. 데이터 삭제, 순차적 애니메이션 등)을 수행하려면 mutableTransitionState를 사용하는 AnimatedVisibility를 사용하도록 하자

enter / exit

기본적인 enter 동작은 fadeIn+expandIn(서서히 나타나면서 커지는)조합이며, exit 또한 그 반대로 생각하면 된다.

4가지의 유형(fade, Expand/Shrink, Sacle, Slide)의 EnterTransitionExitTransition을 지원하며, +를 사용해 결합하여 사용한다(애니메이션 동시진행 -> 결합 순서 상관x) (하단 예시1 코드 참고)

AnimatedVisibilityenter/exit 애니메이션이 모두 완료될 때까지 애니메이션의 상태를 관리하고 대기한다

배치

content에 맞는 레이아웃을 생성하며 모든 자식들은 레이아웃의 상단 시작부분에 정렬된다

RowScope(or ColumnScope).AnimatedVisible 로 정의되어 있기 때문에, Row/Column에 배치되면 해당 컨테이너에 맞게 enter/exit가 조정된다

커스텀

커스텀 애니메이션도 정의할 수 있다 AnimatedVisibilityScopeTransition<EnterExitState>객체를 사용(scope안에서 transition.animatexxx를 사용하면 된다.)(하단 예시2 코드 참고)

커스텀된 애니메이션은 enterexit에서 지정된 내장 애니메이션과 함께 실행되기에 모든 애니메이션을 커스텀하고 싶다면 enter/exitEnterTransition.None으로 설정해서 만들면 된다.

예시 코드

예시1)
AnimatedVisibility(
    visible = visible,
    enter = 
            // 수직으로 슬라이드하며 나타남
            // 초기y가 -40으로 지정하여 위에서 아래로 슬라이드
            slideInVertically(initialOffsetY = { -40 }) 
            // 정렬 기준(Top)에서부터 수직으로 확장되며 나타남
            + expandVertically(expandFrom = Alignment. Top) 
            // 크기가 커지면서 나타남
            + scaleIn(transformOrigin = TransformOrigin(0.5f, 0f)) 
            // 서서히 보이게 나타남
            + fadeIn(initialAlpha = 0.3f),
    exit = slideOutVertically() + shrinkVertically() 
    + fadeOut() + scaleOut(targetScale = 1.2f) 
)
예시2)
AnimatedVisibility(
    ...
) { 
    // transition = Transition<EnterExitState>
    val cornerRadius by transition.animateDp {
        when (it) {
        	// 애니메이션이 아직 실행되지 않은 초기 상태
            EnterExitState.PreEnter -> 0.dp
            // content가 화면에 등장
            EnterExitState.Visible -> 50.dp
            // content가 화면에서 사라질 경우
            EnterExitState.PostExit -> 50.dp}
        }
    Box(Modifier
        .background(
            Color.Red, 
            shape = RoundedCornerShape(cornerRadius))
        .height(100.dp).fillMaxWidth())
}
profile
안녕하세요 😊

0개의 댓글