Jetpack Compose Accompanist
Jetpack Compose Accompanist 는 Compose Supplement Library Set 입니다. Compose 는 미완성 단계이고 XML 및 Android View 생태계를 완전히 대체하기에는 모자란 부분이 있는 것이 사실입니다.
그 부분들을 메우기 위해 Accompanist 는 수많은 편의 기능을 제공합니다.
HorizontalPager, Indicator
HorizontalPager 역시 Accompanist 가 제공하는 기능입니다. 동시에 Indicator 까지 제공하고 있습니다.
그럼에도 불구하고 직접 Indicator 를 구현한 이유는 애니메이션이 없었기 때문입니다.
Accompanist 에서 제공하는 Indicator 는 페이지 갯수 만큼 작은 원이 있고, 그 사이를 색칠된 원이 왔다갔다 하는 것 뿐입니다. 다소 심심할 수 있습니다.
Accompanist 에서 제공하는 Indicator
Custom Indicator
Tl ; DR
소스 코드는 제 깃허브에서 보실 수 있습니다.
GitHub - jangjh123/Jetpack-Compose-CustomView: Jetpack Compose 를 활용한 CustomView 기록용 Repository
Jetpack Compose 를 활용한 CustomView 기록용 Repository. Contribute to jangjh123/Jetpack-Compose-CustomView development by creating an account on GitHub.
github.com
Jetpack Compose Animation
Jetpack Compose 는 뛰어난 애니메이션 구현 편의성을 가졌습니다. 정말 복잡한 애니메이션이 아니라면 어지간해서는 Compose 가 제공하는 API 를 통해 쉽게 구현할 수 있습니다.
이 Indicator 를 XML 환경에서 View 와 그 애니메이션 처리를 통해 구현해야 한다면 굉장히 까다로운 일이었을 겁니다.
구현
@OptIn(ExperimentalPagerApi::class)
@Composable
fun HorizontalPagerIndicator(
modifier: Modifier,
count: Int,
state: PagerState,
focusedColor: Color,
unfocusedColor: Color,
) {
Row(
modifier = modifier
) {
for (i in 0 until count) {
IndicatorSymbol(
currentItemIndex = state.currentPage,
symbolIndex = i,
focusedColor = focusedColor,
unfocusedColor = unfocusedColor
)
}
}
}
Flow 는 다음과 같습니다.
- Pager 의 현재 아이템 인덱스를 파라미터로 전달
- Indicator Symbol 중, Symbol 의 인덱스와 현재 Pager 아이템 인덱스가 같다면 길이를 늘려주고 색상을 변경
Accompanist 가 제공하는 rememberPagerState() 메서드를 통해 PagerState 인스턴스를 생성하고 이를 Pager 의 파라미터로 전달합니다. 해당 PagerState 인스턴스를 그대로 Indicator 파라미터로도 전달해 줍니다. Symbol 에 인덱스를 할당하기 위해, for 문을 돌면서 Symbol Composable 마다 i 값을 인덱스로 할당해줍니다.
@Composable
fun IndicatorSymbol(
currentItemIndex: Int,
symbolIndex: Int,
focusedColor: Color,
unfocusedColor: Color,
) {
val widthState =
animateDpAsState(
targetValue =
if (currentItemIndex == symbolIndex) 24.dp
else 8.dp)
val colorState =
animateColorAsState(
targetValue =
if (currentItemIndex == symbolIndex) focusedColor
else unfocusedColor)
Box(modifier = Modifier
.width(24.dp)
) {
Box(
modifier = Modifier
.clip(
shape = RoundedCornerShape(255.dp)
)
.width(widthState.value)
.height(8.dp)
.background(
color = colorState.value)
.align(Alignment.Center)
)
}
}
animateDpAsState, animatedColorAsState 를 활용하여 길이와 색상을 변경해줍니다.
Symbol 을 Box 로 한 번 더 감싸 준 이유는, 중간 위치는 고정되고 좌우로 길이를 늘어나게 해주기 위함입니다. 별도의 처리를 해주지 않으면 좌측으로 이동할 때는 오른쪽이 길어지고, 우측으로 이동할 때는 왼쪽이 길어집니다. 그것도 나름 괜찮습니다.
Jetpack Compose 에서의 애니메이션 구현이 쉬울 것이라고 생각은 했으나, 이렇게까지 간편하게 구현할 수 있을 줄은 몰랐습니다.
'Android > Android Custom View' 카테고리의 다른 글
[Jetpack Compose] Reorderable LazyList 에 Drag&Drop to Remove 곁들이기 (0) | 2024.01.26 |
---|---|
[Jetpack Compose] ImageCropper 라이브러리 없이 구현하기 Part II (2) | 2023.12.01 |
[Jetpack Compose] ImageCropper 라이브러리 없이 구현하기 (0) | 2022.12.01 |
[XML] AmbientLightView (0) | 2022.06.10 |
[XML] LineWork (0) | 2022.05.12 |