【问题标题】:Jetpack Compose - Restore LazyColumn Scroll StateJetpack Compose - 恢复 LazyColumn 滚动状态
【发布时间】: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滚动状态?

【问题讨论】:

    标签: android kotlin android-jetpack-compose android-jetpack-compose-list 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
              )
          }
      

      【讨论】:

        猜你喜欢
        • 2021-08-13
        • 1970-01-01
        • 1970-01-01
        • 2021-11-26
        • 2021-03-11
        • 2021-06-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-29
        相关资源
        最近更新 更多