首页 > 解决方案 > Jetpack Compose - 恢复 LazyColumn 滚动状态

问题描述

我有一个LazyColumn包含多个LazyRow. 用旧的术语来说,嵌套的 RecyclerView。

我的问题是,LazyColumn移动到新的可组合(不同的选项卡)时不会恢复滚动状态。但是 inner LazyRows 恢复了它们的状态。

例如,打开主屏幕,滚动到底部然后滚动LazyRow到结束,然后打开不同的选项卡并再次返回主选项卡。LazyColumn从顶部开始(不恢复状态),但最后LazyRow恢复它的滚动状态。

主屏幕包含LazyColumn

@Composable
fun HomeScreen(
    homeViewModel: HomeViewModel = hiltViewModel()
) {

    val scrollState = rememberLazyListState()

    LazyColumn(contentPadding = PaddingValues(vertical = 8.dp),
        horizontalAlignment = Alignment.Start,
        verticalArrangement = Arrangement.spacedBy(8.dp),
        state = scrollState,
        modifier = Modifier
            .fillMaxSize()
            .background(MaterialTheme.colors.background)
    ) {
        items(5) {
            TopRatedProducts(homeViewModel = homeViewModel)
        }
    }
}

TopRatedProducts 包含LazyRow

@Composable
fun TopRatedProducts(
    homeViewModel: HomeViewModel = hiltViewModel()
) {
    val topRatedProducts by rememberFlowWithLifecycle(homeViewModel.topRatedProducts)
        .collectAsState(initial = emptyList())

    LazyRow(
        contentPadding = PaddingValues(horizontal = 8.dp), // Space between start and end
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(8.dp), // Space between items
        modifier = Modifier
            .background(Color.Green)
    ) {
        items(topRatedProducts) {
            ProductCardItem(item = it)
        }
    }
}

如何恢复LazyColumn滚动状态?

标签: androidkotlinandroid-jetpack-composeandroid-jetpack-compose-listlazycolumn

解决方案


当您希望在 Fragments 中使用 ComposeView 这种行为时,您应该提及ViewCompositionStrategy

override fun onCreateView(
    inflater: LayoutInflater, container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    return ComposeView(requireContext()).apply {
        // Dispose the Composition when viewLifecycleOwner is destroyed
        setViewCompositionStrategy(
            ViewCompositionStrategy.DisposeOnLifecycleDestroyed(viewLifecycleOwner)
        )
        setContent {
            // content
        }
    }
}

来自文档: 默认情况下,只要视图与窗口分离,Compose 就会处理合成。Compose UI View 类型(如 ComposeView 和 AbstractComposeView)使用定义此行为的 ViewCompositionStrategy。

默认情况下,Compose 使用 DisposeOnDetachedFromWindow 策略。但是,当 Compose UI View 类型用于以下情况时,此默认值可能在某些情况下是不可取的:

  • 片段。组合必须遵循 Fragment 的视图生命周期,以便 Compose UI 视图类型保存状态。

  • 过渡。每当 Compose UI View 被用作转换的一部分时,它将在转换开始时而不是在转换结束时从其窗口中分离,从而导致您的可组合物在它仍在屏幕上时释放其状态。

  • RecyclerView 视图持有者,或您自己的生命周期管理的自定义视图

文档链接:https ://developer.android.com/jetpack/compose/interop/interop-apis#composition-strategy


推荐阅读