Jetpack Compose LazyColumn 以编程方式滚动到项目
Posted
技术标签:
【中文标题】Jetpack Compose LazyColumn 以编程方式滚动到项目【英文标题】:Jetpack Compose LazyColumn programmatically scroll to Item 【发布时间】:2021-03-11 21:16:01 【问题描述】:有没有办法以编程方式将LazyColumn
滚动到列表中的某个项目?我认为可以通过提升LazyColumn
参数state: LazyListState = rememberLazyListState()
来完成,但我不知道如何改变这种状态,例如点击按钮。
【问题讨论】:
【参考方案1】:带1.0.x
LazyListState
支持滚动位置通过
scrollToItem()
函数,“立即”捕捉滚动位置,
animateScrollToItem()
使用动画滚动
类似:
val listState = rememberLazyListState()
// Remember a CoroutineScope to be able to launch
val coroutineScope = rememberCoroutineScope()
LazyColumn(state = listState)
// ...
Button (
onClick =
coroutineScope.launch
// Animate scroll to the 10th item
listState.animateScrollToItem(index = 10)
)
Text("Click")
【讨论】:
【参考方案2】:在 Compose 1.0.0-alpha07 中,没有公共 API,但有一些内部 API 到 LazyListState#snapToItemIndex
。
/**
* Instantly brings the item at [index] to the top of the viewport, offset by [scrollOffset]
* pixels.
*
* Cancels the currently running scroll, if any, and suspends until the cancellation is
* complete.
*
* @param index the data index to snap to
* @param scrollOffset the number of pixels past the start of the item to snap to
*/
@OptIn(ExperimentalFoundationApi::class)
suspend fun snapToItemIndex(
@IntRange(from = 0)
index: Int,
@IntRange(from = 0)
scrollOffset: Int = 0
) = scrollableController.scroll
scrollPosition.update(
index = DataIndex(index),
scrollOffset = scrollOffset,
// `true` will be replaced with the real value during the forceRemeasure() execution
canScrollForward = true
)
remeasurement.forceRemeasure()
也许在即将发布的版本中,我们可以看到更新。
【讨论】:
【参考方案3】:这是我制作粘性标题、列表和滚动的代码
@ExperimentalFoundationApi
@Composable
private fun ListView(data: YourClass)
//this is to remember state, internal API also use the same
val state = rememberLazyListState()
LazyColumn(Modifier.fillMaxSize(), state)
itemsIndexed(items = data.list, itemContent = index, dataItem ->
ItemView(dataItem)// your row
)
// header after some data, according to your condition
stickyHeader
ItemDecoration()// compose fun for sticky header
// More items after header
itemsIndexed(items = data.list2, itemContent = index, dataItem ->
ItemView(dataItem)// your row
)
// scroll to top
// I am scrolling to top every time data changes, use accordingly
CoroutineScope(Dispatchers.Main).launch
state.snapToItemIndex(0, 0)
【讨论】:
【参考方案4】:试试
lazyListState.animateScrollToItem(lazyListState.firstVisibleItemIndex)
@Composable
fun CircularScrollList(
value: Long,
onValueChange: () -> Unit =
)
val lazyListState = rememberLazyListState()
val scope = rememberCoroutineScope()
val items = CircularAdapter(listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9))
scope.launch lazyListState.scrollToItem(items.midIndex())
LazyColumn(
modifier = Modifier
.requiredHeight(height = 120.dp)
.border(width = 1.dp, color = Color.Black),
state = lazyListState,
)
items(items)
if (!lazyListState.isScrollInProgress)
scope.launch
lazyListState.animateScrollToItem(lazyListState.firstVisibleItemIndex)
Text(
text = "$it",
modifier = Modifier.requiredHeight(40.dp),
style = TextStyle(fontSize = 30.sp)
)
class CircularAdapter(
private val content: List<Int>
) : List<Int>
fun midIndex(): Int = Int.MAX_VALUE / 2 + 6
override val size: Int = Int.MAX_VALUE
override fun contains(element: Int): Boolean = content.contains(element = element)
override fun containsAll(elements: Collection<Int>): Boolean = content.containsAll(elements)
override fun get(index: Int): Int = content[index % content.size]
override fun indexOf(element: Int): Int = content.indexOf(element)
override fun isEmpty(): Boolean = content.isEmpty()
override fun iterator(): Iterator<Int> = content.iterator()
override fun lastIndexOf(element: Int): Int = content.lastIndexOf(element)
override fun listIterator(): ListIterator<Int> = content.listIterator()
override fun listIterator(index: Int): ListIterator<Int> = content.listIterator(index)
override fun subList(fromIndex: Int, toIndex: Int): List<Int> =
content.subList(fromIndex, toIndex)
【讨论】:
【参考方案5】:我已经解决了两种方法
一种方式:我选择了这种最好的方式
LaunchedEffect(true)
repeat(Int.MAX_VALUE)
delay(TIME_DELAY_BANNER)
pagerState.animateScrollToPage(page = it % pagerState.pageCount)
两种方式:
var index = pagerState.currentPage
LaunchedEffect(true)
while (true)
delay(TIME_DELAY_BANNER)
if (index == pagerState.pageCount)
index = 0
pagerState.animateScrollToPage(page = index++)
【讨论】:
以上是关于Jetpack Compose LazyColumn 以编程方式滚动到项目的主要内容,如果未能解决你的问题,请参考以下文章
Android Jetpack Compose学习—— Jetpack compose基础布局
Android Jetpack Compose学习—— Jetpack compose基础布局
Android Jetpack Compose学习—— Jetpack compose入门