
무한 페이저를 만들때 아주 단순하게 생각하면 이렇게 만들기 쉽다.
하지만 이 경우, 초기 페이지가 내가 원하는 페이지가 되지 않는다. 실제 배열의 0번째부터 시작해야하는데, 실제 배열의 길이가 바뀌면 초기 페이지도 어떻게 될지 보장 할 수 없게 된다.
val pageCount = Int.MAX_VALUE val pagerState = rememberPagerState( initialPage = Int.MAX_VALUE / 2 )
무한 페이저는 한 두번이 아니라 나도 초기 페이지 계산하는 공식을 때려 맞추고는 했는데
빡대가리라 뭔가 수학적으로 설명을 하는게 안되서… 헤메고 있던 차,
Jetpack Compose Endless Pager만들기 YouTube 강의 영상에서 아주 좋은 댓글을 발견했다.

이 방법의 원리는 정수들이 나눗셈 연산에서 항상 내림되는 특성에 기반한다.
실제 아이템의 갯수가 3개이고 Int.MAX_VALUE
를 쉬운 설명을 위해 15라고 할때
15개의 아이템이 쫙 펼쳐진 페이지들의 모습은 이렇게 된다.
123123123123123
이 것들은 사실 이렇게 묶을 수 있다. 이 페이지 묶음이 연속되어 무한이라는 착시를 일으킨다.
15 / 3 = 5개의 묶음이 생겼다.
[123] [123] [123] [123] [123]
우리는 최종적으로 빨간색 글자가 있는 인덱스를 얻어야 한다.
[123 [123] [123] [123] [123]
5개의 묶음 중 가운데 쯔음은 어딜까? 5 / 2 = 2이다.
2묶음 만큼의 페이지를 지나쳤으므로 2 * 3 = 6이 우리가 찾던 초기 페이지의 Index가 된다.
[123] [123] [123] [123] [123]
0부터 시작하는 인덱스의 특성상 바로 숫자를 써버리면 된다.
123123123123123
0123456
val actualPageCount = 3 val pageCount = Int.MAX_VALUE val maxNumOfRounds = Int.MAX_VALUE / actualPageCount val pagerState = rememberPagerState( initialPage = (maxNumOfRounds / 2) * actualPageCount )
import androidx.compose.foundation.ExperimentalFoundationApi | |
import androidx.compose.foundation.background | |
import androidx.compose.foundation.layout.Box | |
import androidx.compose.foundation.layout.fillMaxSize | |
import androidx.compose.foundation.layout.height | |
import androidx.compose.foundation.pager.HorizontalPager | |
import androidx.compose.foundation.pager.PagerState | |
import androidx.compose.foundation.pager.rememberPagerState | |
import androidx.compose.foundation.shape.RoundedCornerShape | |
import androidx.compose.material3.MaterialTheme | |
import androidx.compose.material3.Surface | |
import androidx.compose.material3.Text | |
import androidx.compose.runtime.Composable | |
import androidx.compose.ui.Alignment | |
import androidx.compose.ui.Modifier | |
import androidx.compose.ui.graphics.Color | |
import androidx.compose.ui.tooling.preview.Preview | |
import androidx.compose.ui.unit.dp | |
@OptIn(ExperimentalFoundationApi::class) | |
@Composable | |
fun TestScreen() { | |
val actualPageCount = 3 | |
val pageCount = Int.MAX_VALUE | |
val maxNumOfRounds = Int.MAX_VALUE / actualPageCount | |
val pagerState = rememberPagerState( | |
initialPage = (maxNumOfRounds / 2) * actualPageCount | |
) | |
HorizontalPager( | |
modifier = Modifier | |
.fillMaxSize() | |
.background(Color.LightGray), | |
pageCount = pageCount, | |
state = pagerState, | |
pageSpacing = 10.dp, | |
) { page -> | |
Box( | |
modifier = Modifier.fillMaxSize() | |
) { | |
Card( | |
page = page % actualPageCount, | |
modifier = Modifier | |
.align(Alignment.Center) | |
.height(300.dp) | |
) | |
} | |
} | |
} | |
@Composable | |
fun Card(page: Int, modifier: Modifier = Modifier) { | |
Surface( | |
modifier = modifier, | |
color = Color.DarkGray, | |
shape = RoundedCornerShape(16.dp) | |
) { | |
Box(modifier = Modifier.fillMaxSize()) { | |
Text( | |
text = "Page $page", | |
modifier = Modifier.align(Alignment.Center), | |
style = MaterialTheme.typography.headlineLarge, | |
color = Color.White | |
) | |
} | |
} | |
} |
도움이 되셨다면, 공감!