반응형
자동으로 Scroll 되고 사용자가 Scroll 할 수 있는 Pager 가 필요한 경우가 있다.
얼마전까지 Accompanist 에 있었지만 deprecated 되어서 구현했다.
https://play.google.com/store/apps/details?id=com.danchoo.tagalbum&hl=ko
중요한 것은 pagerState의 현재 page 값을 받아오는 state다.
pagerState.settledPage
The page that is currently "settled". This is an animation/gesture unaware page in the sense that it will not be updated while the pages are being scrolled, but rather when the animation/scroll settles. Please refer to the sample to learn how to use this API.
현재 "정해진" 페이지입니다. 이것은 페이지가 스크롤되는 동안 업데이트되지 않고 애니메이션/스크롤이 안정될 때 업데이트된다는 점에서 애니메이션/제스처를 인식하지 못하는 페이지입니다. 이 API를 사용하는 방법을 알아보려면 샘플을 참조하십시오.
https://smartstore.naver.com/happysiso
스크롤되는 동안 업데이트되지 않고 애니메이션/스크롤이 안정될 때 업데이트된다는 점에서 애니메이션/제스처를 인식하지 못하는 페이지입니다.
스크롤이 끝난 시점에 변경이 된다.
import androidx.compose.foundation.pager.HorizontalPager
import androidx.compose.foundation.pager.PagerState
import androidx.compose.foundation.pager.rememberPagerState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@Composable
fun AutoScrollablePager(
modifier: Modifier = Modifier,
pagerState: PagerState = rememberPagerState(initialPage = 1),
itemCount: Int,
scrollTime: Long = PAGER_AUTO_SCROLL_TIME,
items: @Composable (page: Int) -> Unit,
onPageChanged: (page: Int) -> Unit = {}
) {
LaunchedEffect(key1 = pagerState.settledPage) {
var currentPage = pagerState.settledPage
when {
isAfterLastPage(itemCount, pagerState.settledPage) -> {
currentPage = 1
pagerState.scrollToPage(1)
}
isBeforeFistPage(pagerState.settledPage) -> {
currentPage = itemCount
pagerState.scrollToPage(itemCount)
}
else -> Unit
}
onPageChanged(currentPage)
}
LaunchedEffect(key1 = pagerState.settledPage) {
launch {
delay(scrollTime)
pagerState.animateScrollToPage(pagerState.currentPage + 1)
}
}
HorizontalPager(
modifier = modifier,
pageCount = itemCount + 2,
state = pagerState
) {
val page = getCurrentPage(itemCount, it)
items(page)
}
}
/**
* 무한 스크롤 하기 위한 마지막 더미 페이지 인지 확인
*/
private fun isAfterLastPage(itemCount: Int, currentPage: Int): Boolean {
return itemCount + 1 == currentPage
}
/**
* 무한 스크롤 하기 위한 첫번째 더미 페이지 인지 확인
*/
private fun isBeforeFistPage(currentPage: Int): Boolean {
return currentPage == 0
}
/**
* 무한 스크롤 하기 위한 페이지를 제외한 실제 페이지 index
*/
private fun getCurrentPage(itemCount: Int, currentPage: Int): Int {
return when {
isAfterLastPage(itemCount, currentPage) -> 0
isBeforeFistPage(currentPage) -> itemCount - 1
else -> currentPage - 1
}
}
private const val PAGER_AUTO_SCROLL_TIME = 3000L
사용 예제
@Composable
fun TestComposable(
modifier: Modifier = Modifier,
items: List<String>
) {
AutoScrollablePager(
modifier = modifier,
itemCount = items.size,
items = { page ->
TestComposableItem(item = items[page])
},
onPageChanged = { page ->
Log.d("AutoScrollablePager", "current page $page")
}
)
}
@Composable
fun TestComposableItem(
modifier: Modifier = Modifier,
item: String
) {
Text(text = item)
}
반응형
댓글