首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >RecyclerView与StaggeredGridLayoutManager在ViewPager中,返回到片段时自动排列项目

RecyclerView与StaggeredGridLayoutManager在ViewPager中,返回到片段时自动排列项目
EN

Stack Overflow用户
提问于 2021-01-02 13:46:58
回答 2查看 775关注 0票数 3

我在应用程序中使用导航组件,使用google (这里)。我的问题是,当回到一个片段,t-他滚动的位置没有失去,但它重新排列的项目和移动最高可见的项目,以便这些项目的顶部对齐的回收视图顶部。请看这个:

在进入下一个片段之前:

回到碎片之后:

这个问题很重要,因为有些时候单击的项目会下降,直到向下滚动才会被看到。如何防止这种行为?

请考虑:

  • 如果使用导航组件更改片段,则存在此问题。如果使用supportFragmentManager.beginTransaction()启动片段或启动其他活动,然后转到该片段,则可以。但是,如果我使用导航组件导航到另一个片段,就会存在这个问题(可能是因为重新创建了片段)。
  • 此外,如果在ViewPager中使用片段,也存在这个问题。例如,recyclerView在一个用ViewPagerAdapter处理的片段中,而viewPager在使用导航组件打开的HomeFragment中。如果recyclerView在HomeFragment中,就没有问题。
  • LinearLayoutManager没有问题。只对StaggeredGridLayoutManager。
  • 如果使用ViewPager2和FragmentStatePagerAdapter也没有区别
  • 我试图防止片段的重新创建(通过这个解决方案),但没有解决。

更新:您可以从 这里克隆带有此问题的项目

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-01-06 13:13:35

使用Navigation Component + ViewPager + StaggeredGridLayoutManager时,在重新创建Fragment时返回了错误的recyclerView.computeVerticalScrollOffset()

通常,支持库中的所有布局管理器都知道如何保存和恢复滚动位置,但在这种情况下,我们必须对此负责。

代码语言:javascript
运行
复制
class TestFragment : Fragment(R.layout.fragment_test) {

    private val testListAdapter: TestListAdapter by lazy {
        TestListAdapter()
    }

    private var layoutManagerState: Parcelable? = null

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        postListView.apply {
            layoutManager = StaggeredGridLayoutManager(
                2, StaggeredGridLayoutManager.VERTICAL
            ).apply {
                gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS
            }
            setHasFixedSize(true)

            adapter = testListAdapter
        }

        testListAdapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT

    }

    override fun onPause() {
        saveLayoutManagerState()
        super.onPause()
    }

    override fun onViewStateRestored(savedInstanceState: Bundle?) {
        super.onViewStateRestored(savedInstanceState)
        restoreLayoutManagerState()
    }

    private fun restoreLayoutManagerState () {
        layoutManagerState?.let { postListView.layoutManager?.onRestoreInstanceState(it) }
    }

    private fun saveLayoutManagerState () {
        layoutManagerState = postListView.layoutManager?.onSaveInstanceState()
    }
}

源代码:65539771

票数 2
EN

Stack Overflow用户

发布于 2021-01-05 13:46:11

导航组件行为在从一个片段导航到另一个片段时是正常的。我的意思是,执行来自前一个片段的onDestroyView()方法,因此它意味着您的视图被销毁,而不是该片段。记住这个片段有两个生命周期--一个是片段的生命周期,另一个是视图的生命周期,它有一个视频

此外,在问题跟踪器中注册了一些问题,以便在某些情况下避免这种行为,并且GitHub问题:

问题是,当您有大量重新创建的片段时,更容易不销毁它,只添加一个片段。所以,当你回去的时候,它是不会被重新创造的。但是,因为这种行为不是导航组件的一部分。

解决方案

  • 最简单的解决方案是不使用导航组件并使用贸易方式,因为您可以看到这在您的用例中非常有效。
  • 您可以只对这个用例使用传统的方法,也可以在其他情况下使用导航组件。
  • 您可以在活动中膨胀此视图。所以你加入了联合国的活动
  • 但是,如果前面的树选项是不可能的。您可以尝试以下方法:
代码语言:javascript
运行
复制
- If you are using viewModel, you can use [SaveState](https://developer.android.com/topic/libraries/architecture/viewmodel-savedstate). Basically, it can save the data from your fragment, it is like a map data structure, so you can save positions from your list or recycler view. When go back to this fragment, get the position from this saveState object and use `scrollToPosition` method in order to add the real position.
- Recycler view have methods for restore positions. You can see the uses cases for that, because first you need the data and then add the real position, for more details you can visit [this link](https://www.facebook.com/HailAndroidDevs/posts/222285346153647). This configuration for recycler view is useful also when you lose memory and you need to recreate the recycler view with asynchronous data.

最后,如果您想了解片段如何使用导航组件的更多信息,您可以看到这个链接

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65539771

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档