简体   繁体   English

Jetpack Compose - 恢复 LazyColumn Scroll State

[英]Jetpack Compose - Restore LazyColumn Scroll State

I have a LazyColumn that contains multiple LazyRow .我有一个包含多个LazyColumnLazyRow In old terms, nested RecyclerView.用旧话说,嵌套的 RecyclerView。

My problem is, LazyColumn does not restore scroll state when move to a new composable (Different tab).我的问题是,当移动到新的可组合项(不同选项卡)时, LazyColumn不会恢复滚动 state。 But inner LazyRow s restore their states.但是内部LazyRow恢复它们的状态。

For example, open home screen, scroll to bottom then scroll LazyRow to end then open a different tab and back to home tab again.例如,打开主屏幕,滚动到底部然后滚动LazyRow到结束然后打开一个不同的选项卡并再次返回到主选项卡。 LazyColumn starts from top (does not restore state) but the last LazyRow restore it's scroll state. LazyColumn从顶部开始(不恢复状态)但最后一个LazyRow恢复它的滚动 state。

HomeScreen that contains LazyColumn包含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 that contains LazyRow包含 LazyRow 的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)
        }
    }
}

How can I restore LazyColumn scroll state?如何恢复LazyColumn滚动条 state?

You should mention ViewCompositionStrategy when you want this behaviour with ComposeView in Fragments .当您希望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
        }
    }
}

From docs: By default, Compose disposes of the Composition whenever the view becomes detached from a window. Compose UI View types such as ComposeView and AbstractComposeView use a ViewCompositionStrategy that defines this behavior.来自文档:默认情况下,只要视图与 window 分离,Compose 就会处理 Composition。Compose UI View 类型(例如 ComposeView 和 AbstractComposeView)使用定义此行为的 ViewCompositionStrategy。

By default, Compose uses the DisposeOnDetachedFromWindow strategy.默认情况下,Compose 使用 DisposeOnDetachedFromWindow 策略。 However, this default value might be undesirable in some situations when the Compose UI View types are used in:但是,当 Compose UI View 类型用于以下情况时,在某些情况下可能不需要此默认值:

  • Fragments.碎片。 The Composition must follow the fragment's view lifecycle for Compose UI View types to save state. Composition 必须遵循 Compose UI View 类型的片段视图生命周期才能保存 state。

  • Transitions.过渡。 Anytime the Compose UI View is used as part of a transition, it will be detached from its window when the transition starts instead of when the transition ends, thus causing your composable to dispose of its state while it is still on screen.每当 Compose UI View 用作过渡的一部分时,它将在过渡开始时而不是在过渡结束时与其 window 分离,从而导致您的可组合项在其仍在屏幕上时处理其 state。

  • RecyclerView view holders, or your own lifecycle-managed custom View RecyclerView 视图持有者,或您自己的生命周期管理的自定义视图

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

Try the following at the end of your HomeScreen() function:HomeScreen() function 的末尾尝试以下操作:

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

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

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