본문 바로가기
Android/Kotlin

[Android] Compose Auto Scroll pager

by DnaJ 2023. 7. 24.
반응형

 

자동으로 Scroll 되고 사용자가 Scroll 할 수 있는 Pager 가 필요한 경우가 있다.

 

얼마전까지 Accompanist 에 있었지만 deprecated 되어서 구현했다.

 

중요한 것은 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

 

해피시소마켓 : 네이버쇼핑 스마트스토어

SISO

smartstore.naver.com

 

 

스크롤되는 동안 업데이트되지 않고 애니메이션/스크롤이 안정될 때 업데이트된다는 점에서 애니메이션/제스처를 인식하지 못하는 페이지입니다. 

스크롤이 끝난 시점에 변경이 된다.

 

 

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)
}
반응형

댓글