kotlin 记住惰性列滚动位置- Jetpack合成

ujv3wf0j  于 2023-01-13  发布在  Kotlin
关注(0)|答案(5)|浏览(219)

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

@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
            )
        }
    }
}
oymdgrw7

oymdgrw71#

如果你真的想保存它,你必须把它保存在一个类似视图模型的地方。remember ed的东西只会持续到Composable被销毁。如果你导航到另一个屏幕,以前的Composable和滚动状态都会被销毁

htrmnn0y

htrmnn0y2#

/**
 * 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")
)
taor4pac

taor4pac3#

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

上面我定义了一个helper函数,当组合对象被释放时,它可以保持滚动状态。所需要的只是一个带有滚动位置变量的ViewModel。
希望这对某人有帮助!

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

x8diyxa74#

@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
    }
}

上面我定义了一个helper函数,用于在组合对象被处理时保持滚动状态。所需的只是一个带有firstVisibleItemIdx和firstVisibleItemOffet变量的ViewModel。

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

wooyq4lh5#

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

相关问题