伴奏库中的 HorizontalPager 负责创建一个简单的 ViewPager;有没有办法可以两端无限滑动?
@ExperimentalPagerApi
@Composable
fun AutoScrollPagerHorizontal(d: List<Stem>?) {
var data: MutableList<Stem> = d?.toMutableList() ?: mutableListOf()
if (data.isNullOrEmpty()) return
val pageState = rememberPagerState(pageCount = data.size)
HorizontalPager(
state = pageState
) {
Card(
Modifier
.height(240.dp)
.padding(start = 16.dp, end = 16.dp, top = 8.dp, bottom = 8.dp)
) {
Image(
painter = rememberGlidePainter(
request = data[it].icon,
),
contentDescription = data[it].title,
contentScale = ContentScale.FillBounds
)
}
}
}
此代码正确生成视图页面,但在到达数据的最后一个索引后不会滚动到第 0 个索引。
LaunchedEffect(key1 = pagerState.currentPage) {
launch {
delay(3000)
with(pagerState) {
val target = if (currentPage < pageCount - 1) currentPage + 1 else 0
animateScrollToPage(
page = target,
animationSpec = tween(
durationMillis = 500,
easing = FastOutSlowInEasing
)
)
}
}
}
Modifier.pointerInput(Unit) {
detectHorizontalDragGestures { change, dragAmount ->
change.consumeAllChanges()
when {
dragAmount < 0 -> {
coroutineScope.launch { /* right */
if (pageState.currentPage == data.lastIndex) {
pageState.animateScrollToPage(0)
} else {
pageState.animateScrollToPage(pageState.currentPage + 1)
}
}
}
dragAmount > 0 -> { /* left */
coroutineScope.launch {
if (pageState.currentPage == 0) {
pageState.animateScrollToPage(data.lastIndex)
} else {
pageState.animateScrollToPage(pageState.currentPage - 1)
}
}
}
}
}
}
@Composable
fun Banner(
modifier: Modifier = Modifier,
cornerRoundSize: RoundedCornerShape,
list: List<String>?,
autoPlay: Boolean = true,
indicatorColor: Color = Color.White,
interval: Long = 5000L,
onClick: () -> Unit,
) {
if (list?.isNotEmpty() == true) {
val pagerState =
rememberPagerState(initialPage = 0, pageCount = { list.size })
// Auto play
LaunchedEffect(key1 = autoPlay) {
if (autoPlay) {
while (true) {
delay(interval)
with(pagerState) {
scrollToPage(page = (currentPage + 1) % list.size)
}
}
}
}
Box(modifier = modifier) {
HorizontalPager(
state = pagerState,
) {
Card(
modifier = Modifier
.clickableNoRipple { onClick() }
.clip(cornerRoundSize)
.fillMaxWidth()
.aspectRatio(1.78f)
) {
AsyncImage(
model = list[it],
contentDescription = null,
modifier = modifier.fillMaxSize(),
)
}
}
// Indicator
Row(
modifier = Modifier
.align(Alignment.BottomCenter)
.padding(bottom = 16.dp),
horizontalArrangement = Arrangement.Center,
) {
list.forEachIndexed { index, _ ->
val color =
if (index == pagerState.currentPage) indicatorColor else Color.Gray
if (index > 0) Spacer(modifier = Modifier.width(4.dp))
Box(
modifier = Modifier
.size(6.dp)
.clip(CircleShape)
.background(color)
)
}
}
}
}
}