[Android] 인스타그램 스토리 Page Indicator 만들기

uuranus·2024년 10월 3일
0
post-thumbnail

기존 애니메이션

실제 인스타그램 스토리 page indicator

인스타 스토리를 보면 위에 바느질처럼 되어있는 page indicator를 본 적이 있을 것이다. 오늘은 이 page indicator를 만들어 볼 것이다.

기본 UI 세팅

val dotHeight = 4.dp

Row(
    modifier = modifier
        .fillMaxWidth()
        .wrapContentHeight(),
    verticalAlignment = Alignment.CenterVertically,
    horizontalArrangement = Arrangement.spacedBy(4.dp)
) {
    repeat(pageCount) { index ->
        Box(
            modifier = Modifier
                .height(dotHeight)
                .weight(1f)
                .background(
                    color = if (index < currentPage) {
                        Color.White.copy(alpha = 0.8f)
                    } else {
                        Color.White.copy(alpha = 0.4f)
                    },
                    shape = RoundedCornerShape(16.dp)
                )
        )
    }
}

Row를 통해서 pageCount만큼 일정 크기로 Box를 그려주고 currentPage에 따라서 alpha값으로 몇 페이지까지 봤는지 표시해주었다.

현재 페이지 애니메이션

현재 페이지는 일정 시간동안 page가 보여지고 나면 다음 페이지로 자동으로 넘어간다. 현재 페이지가 보여지는 시간이 몇 초 남았는지 보여주는 애니메이션을 currentPage Box에 추가로 설정해주었다.

val scaleAnimatable = remember(currentPage) { Animatable(0f) }

LaunchedEffect(currentPage) {
    scaleAnimatable.animateTo(
        targetValue = 1f,
        animationSpec = tween(
            durationMillis = pageDuration,
            easing = LinearEasing
        )
    )

    if (scaleAnimatable.value == 1f) {
        onPageAnimationEnded()
    }
}

repeat(pageCount) { index ->
    Box(
        modifier = Modifier
            .height(dotHeight)
            .weight(1f)
            .background(
                if (index < currentPage) {
                    Color.White.copy(alpha = 0.8f)
                } else {
                    Color.White.copy(alpha = 0.4f)
                },
                shape = RoundedCornerShape(16.dp)
            )
    ) {
        if (index == currentPage) {
            Box(
                modifier = Modifier
                    .height(dotHeight)
                    .fillMaxWidth()
                    .graphicsLayer {
                        scaleX = scale.value
                        transformOrigin = TransformOrigin(0f, 0.5f)
                    }
                    .background(
                        Color.White.copy(alpha = 0.8f)
                    )
            )
        }
    }
}

scale을 통해서 애니메이션을 설정해주었고 transforOrigin을 변경해서 왼쪽부터 사이즈가 커지도록 설정해주었다.
그리고 animation이 끝나면 onPageAnimationEnded()를 통해서 다음 데이터로 넘어갈 수 있도록 알려주었다.

그럼 이렇게 만들어진다!

깃허브 링크

https://github.com/uuranus/compose-animations

profile
Frontend Developer

0개의 댓글