繁体   English   中英

记住 LazyColumn Scroll Position - Jetpack Compose

[英]Remember LazyColumn Scroll Position - Jetpack Compose

当我从一个可组合屏幕导航到另一个时,我试图保存/记住 LazyColumn 滚动条 position。 即使我将 rememberLazyListState 传递给 LazyColumn,在我返回第一个可组合屏幕后,滚动条 position 也不会保存。 有人可以帮我吗?

@ExperimentalMaterialApi
@Composable
fun DisplayTasks(
    tasks: List<Task>,
    navigateToTaskScreen: (Int) -> Unit
) {
    val listState = rememberLazyListState()

    LazyColumn(state = listState) {
        itemsIndexed(
            items = tasks,
            key = { _, task ->
                task.id
            }
        ) { _, task ->
            LazyColumnItem(
                toDoTask = task,
                navigateToTaskScreen = navigateToTaskScreen
            )
        }
    }
}
/**
 * Static field, contains all scroll values
 */
private val SaveMap = mutableMapOf<String, KeyParams>()

private data class KeyParams(
    val params: String = "",
    val index: Int,
    val scrollOffset: Int
)

/**
 * Save scroll state on all time.
 * @param key value for comparing screen
 * @param params arguments for find different between equals screen
 * @param initialFirstVisibleItemIndex see [LazyListState.firstVisibleItemIndex]
 * @param initialFirstVisibleItemScrollOffset see [LazyListState.firstVisibleItemScrollOffset]
 */
@Composable
fun rememberForeverLazyListState(
    key: String,
    params: String = "",
    initialFirstVisibleItemIndex: Int = 0,
    initialFirstVisibleItemScrollOffset: Int = 0
): LazyListState {
    val scrollState = rememberSaveable(saver = LazyListState.Saver) {
        var savedValue = SaveMap[key]
        if (savedValue?.params != params) savedValue = null
        val savedIndex = savedValue?.index ?: initialFirstVisibleItemIndex
        val savedOffset = savedValue?.scrollOffset ?: initialFirstVisibleItemScrollOffset
        LazyListState(
            savedIndex,
            savedOffset
        )
    }
    DisposableEffect(Unit) {
        onDispose {
            val lastIndex = scrollState.firstVisibleItemIndex
            val lastOffset = scrollState.firstVisibleItemScrollOffset
            SaveMap[key] = KeyParams(params, lastIndex, lastOffset)
        }
    }
    return scrollState
}

使用示例

LazyColumn(
    state = rememberForeverLazyListState(key = "Overview")
)

好吧,如果您真的想保存它,则必须将其存储为类似视图模型的东西,并且它仍然保留下来。 remember东西只持续到可组合被销毁。 如果您导航到另一个屏幕,则先前的 Composable 将被销毁,并且滚动状态也会随之销毁

@Composable
fun persistedScrollState(viewModel: ParentViewModel): ScrollState {
    val scrollState = rememberScrollState(viewModel.scrollPosition)
    DisposableEffect(key1 = null) {
        onDispose {
            viewModel.scrollPosition = scrollState.value
        }
    }
    return scrollState
}

上面我定义了一个辅助函数,用于在处理可组合项时保持滚动状态。 所需要的只是一个带有滚动位置变量的 ViewModel。

希望这对某人有帮助!

Column(modifier = Modifier
   .fillMaxSize()
   .verticalScroll(
       persistedScrollState(viewModel = viewModel)
   ) {
   //Your content here
}
@Composable
fun persistedLazyScrollState(viewModel: YourViewModel): LazyListState {
        val scrollState = rememberLazyListState(viewModel.firstVisibleItemIdx, viewModel.firstVisibleItemOffset)
        DisposableEffect(key1 = null) {
            onDispose {
                viewModel.firstVisibleItemIdx = scrollState.firstVisibleItemIndex
                viewModel.firstVisibleItemOffset = scrollState.firstVisibleItemScrollOffset
            }
        }
        return scrollState
    }
}

在上面,我定义了一个帮助程序 function 以在处置可组合项时保留滚动条 state。 所需要的只是一个带有 firstVisibleItemIdx 和 firstVisibleItemOffet 变量的 ViewModel。

Column(modifier = Modifier
   .fillMaxSize()
   .verticalScroll(
       persistedScrollState(viewModel = viewModel)
   ) {
   //Your content here
}

导航到下一个屏幕时, LazyColumn应该立即保存滚动条 position。 如果它不起作用,这可能是此处描述的错误(问题跟踪器)。 基本上检查列表是否在更改屏幕时变空,例如,因为您观察到冷流或 LiveData(因此使用初始值)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM