如何在 Jetpack Compose 的 LazyColumn/LazyRow 中禁用和启用滚动?

d-f*_*erx 7 android kotlin android-jetpack-compose

我想在LazyColumn.

本身似乎没有任何相关功能LazyListState或相关参数LazyColumn。如何在 Compose 中实现这一目标?

Phi*_*hov 40

自1.2.0 起,userScrollEnabled参数被添加LazyColumn, LazyRow, 和LazyVerticalGrid

LazyColumn(userScrollEnabled = false) ...
Run Code Online (Sandbox Code Playgroud)

1.1.0及之前版本的回答:

@Ryan 的解决方案还将禁用以编程方式调用的滚动。

这是维护者在此功能请求中提出的解决方案。它将禁用滚动,允许编程滚动以及子视图触摸。

LazyColumn(userScrollEnabled = false) ...
Run Code Online (Sandbox Code Playgroud)

用法:

LazyColumn(
    modifier = Modifier.disabledVerticalPointerInputScroll()
) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)


Rya*_*ley 10

没有(目前)内置的方法可以做到这一点,这是一个合理的功能请求。

但是,scrollAPI 足够灵活,我们可以自己添加。基本上,我们创建一个永无止境的假滚动MutatePriority.PreventUserInput以防止滚动,然后使用相同优先级的无操作滚动取消第一次“滚动”并重新启用滚动。

这里有两个LazyListState用于禁用/重新启用滚动的实用函数,以及它们的演示(需要一些导入,但 Android Studio 应该为您推荐它们)。

请注意,因为我们正在控制滚动来执行此操作,因此调用reenableScrolling还将取消任何正在进行的滚动或甩动(也就是说,您应该只在禁用滚动并希望重新启用它时调用它,而不仅仅是确认它已启用)。

fun LazyListState.disableScrolling(scope: CoroutineScope) {
    scope.launch {
        scroll(scrollPriority = MutatePriority.PreventUserInput) {
            // Await indefinitely, blocking scrolls
            awaitCancellation()
        }
    }
}

fun LazyListState.reenableScrolling(scope: CoroutineScope) {
    scope.launch {
        scroll(scrollPriority = MutatePriority.PreventUserInput) {
            // Do nothing, just cancel the previous indefinite "scroll"
        }
    }
}

@Composable
fun StopScrollDemo() {
    val scope = rememberCoroutineScope()
    val state = rememberLazyListState()
    Column {
        Row {
            Button(onClick = { state.disableScrolling(scope) }) { Text("Disable") }
            Button(onClick = { state.reenableScrolling(scope) }) { Text("Re-enable") }
        }
        LazyColumn(Modifier.fillMaxWidth(), state = state) {
            items((1..100).toList()) {
                Text("$it", fontSize = 24.sp)
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 看起来这会阻止与子可组合项的所有交互,包括文本字段、下拉菜单等。假设这是因为“MutatePriority.PreventUserInput”阻止了所有输入和阻止?在 Accompanist Pager 中询问的原因是使用 `LazyListState` 和 `PagerState` 作为 `ScrollState` 委托 - 我想禁用用户滚动,同时允许子页面和可组合项仍然使用事件,无论如何这可能只是事件的传递,只是不使用滚动事件(寻呼机 API 目前不灵活且有限)? (7认同)

Dar*_*son 7

NestedScrollConnection 允许您使用应用于惰性列或行的任何滚动。当 true 时,所有可用的滚动都会被消耗。如果为 false,则不会消耗任何内容并且滚动会正常发生。有了这些信息,您就可以了解如何通过按某个因子返回偏移倍数来扩展慢速/快速滚动。

fun Modifier.scrollEnabled(
    enabled: Boolean,
) = nestedScroll(
    connection = object : NestedScrollConnection {
        override fun onPreScroll(
            available: Offset,
            source: NestedScrollSource
        ): Offset = if(enabled) Offset.Zero else available
    }
)
Run Code Online (Sandbox Code Playgroud)

它可以这样使用:

LazyColumn(
    modifier = Modifier.scrollEnabled(
        enabled = enabled, //provide a mutable state boolean here
    )
){
    ...
Run Code Online (Sandbox Code Playgroud)

但是,这确实会阻止程序化滚动。