[英]Jetpack Compose LazyColumn programmatically scroll to Item
Is there any way to programmatically scroll LazyColumn
to some item in the list?有没有办法以编程方式将
LazyColumn
滚动到列表中的某个项目? I thought that it can be done by hoisting the LazyColumn
argument state: LazyListState = rememberLazyListState()
but I have no idea how I can change this state eg on Button click.我认为可以通过提升
LazyColumn
参数state: LazyListState = rememberLazyListState()
来完成,但我不知道如何更改此 state 例如在按钮单击时。
The LazyListState
supports the scroll position via LazyListState
通过以下方式支持滚动 position
scrollToItem()
function, which 'immediately' snaps the scroll position, scrollToItem()
function,它“立即”捕捉滚动 position,animateScrollToItem()
which scrolls using an animation animateScrollToItem()
使用 animation 滚动Something like:就像是:
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")
}
In Compose1.0.0-alpha07 , There is no public API, But some internal API is there to LazyListState#snapToItemIndex
.在 Compose1.0.0-alpha07中,没有公共 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()
}
Maybe in the upcoming release, we can see the updates.也许在即将发布的版本中,我们可以看到更新。
Here is my code that makes sticky headers, list and scroll这是我制作粘性标题、列表和滚动的代码
@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)
}
}
}
try with尝试
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)
}
I have solved 2 way我已经解决了2种方式
one way: I choosed this best way一种方式:我选择了这种最好的方式
LaunchedEffect(true) {
repeat(Int.MAX_VALUE) {
delay(TIME_DELAY_BANNER)
pagerState.animateScrollToPage(page = it % pagerState.pageCount)
}
}
two way:两种方式:
var index = pagerState.currentPage
LaunchedEffect(true) {
while (true) {
delay(TIME_DELAY_BANNER)
if (index == pagerState.pageCount) {
index = 0
}
pagerState.animateScrollToPage(page = index++)
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.