Jetpack Compose - 恢复 LazyColumn 滚动状态

Posted

技术标签:

【中文标题】Jetpack Compose - 恢复 LazyColumn 滚动状态【英文标题】:Jetpack Compose - Restore LazyColumn Scroll State 【发布时间】:2021-09-28 17:37:57 【问题描述】:

我有一个包含多个LazyRowLazyColumn。在旧术语中,嵌套的 RecyclerView。

我的问题是,LazyColumn 在移动到新的可组合(不同的选项卡)时不会恢复滚动状态。但是内部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)
        
    

包含LazyRow的TopRatedProducts

@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滚动状态?

【问题讨论】:

【参考方案1】:

当您希望使用 ComposeView in Fragments 进行此行为时,您应该提及 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

【讨论】:

【参考方案2】:

HomeScreen() 函数的末尾尝试以下操作:

    LaunchedEffect(scrollState.firstVisibleItemScrollOffset) 
        scrollState.scrollToItem(
            scrollState.firstVisibleItemIndex,
            scrollState.firstVisibleItemScrollOffset
        )
    

【讨论】:

以上是关于Jetpack Compose - 恢复 LazyColumn 滚动状态的主要内容,如果未能解决你的问题,请参考以下文章

修复了 Jetpack Compose 中 LazyColumn 内的网格?

php facetwp jetpack lazy load compat

Jetpack All In Compose ?看各种Jetpack库在Compose中的使用

Android Jetpack Compose学习—— Jetpack compose基础布局

Android Jetpack Compose学习—— Jetpack compose基础布局

Android Jetpack Compose学习—— Jetpack compose基础布局