본문 바로가기
Android/Kotlin

[Android] Compose Auto Scroll pager

by DnaJ 2023. 7. 24.
반응형

 

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

 

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

 

https://play.google.com/store/apps/details?id=com.danchoo.tagalbum&hl=ko

 

태그앨범 - Google Play 앱

사진과 앨범을 태그로 관리하세요. 결혼식, 팬클럽, 동호회등 원하는 카테고리를 만들어 정리해보세요. 사진에 태그를 설정하여 손쉽게 찾아보세요!

play.google.com

 

 

중요한 것은 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)
}
반응형

댓글