android - RecyclerView 与 ViewPager 中的 StaggeredGridLayoutManager,返回 fragment 时自动排列项目

标签 android android-fragments android-viewpager android-architecture-navigation staggeredgridlayoutmanager

我在我的应用程序中使用导航组件,使用谷歌高级示例(here)。 我的问题是当返回到 fragment 时,滚动位置不会丢失 但它会重新排列项目并移动最高的可见项目,以便这些项目的顶部与 recyclerview 的顶部对齐。请看这个:

enter image description here

在进入下一个 fragment 之前:

enter image description here

回到 fragment 后:

enter image description here

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

请考虑:

  • 如果使用导航组件更改 fragment ,则存在此问题。如果使用 supportFragmentManager.beginTransaction() 开始 fragment 或开始另一个 Activity 然后转到此 fragment ,则可以。但如果我使用导航组件导航到另一个 fragment ,则存在此问题。(可能是因为重新创建 fragment )

  • 如果在 ViewPager 中使用 fragment ,也存在此问题。即 recyclerView 位于使用 ViewPagerAdapter 处理的 fragment 中,而 viewPager 位于使用 Navigation 组件打开的 HomeFragment 中。如果 recyclerView 在 HomeFragment 中就没有问题。

  • LinearLayoutManager 没问题。仅与 StaggeredGridLayoutManager 一起使用。

  • 如果使用 ViewPager2 和 FragmentStatePagerAdapter 没有区别

  • 我试图阻止重新创建 fragment (通过这个 solution )但没有解决。

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

最佳答案

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

一般来说,支持库中 bundle 的所有布局管理器都已经知道如何保存和恢复滚动位置,但在这种情况下,我们必须为此负责。

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()
    }
}

源代码:https://github.com/dautovicharis/MyStaggeredListSample/tree/q_65539771

关于android - RecyclerView 与 ViewPager 中的 StaggeredGridLayoutManager,返回 fragment 时自动排列项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65539771/

相关文章:

java - 安卓 fragment 问题

android - 如何隐藏布局下的按钮

java - Google Firebase 实时数据库无法正常工作,因为一切都已正确设置

java - 如何将 Activity 更改为 Fragment

android - OnBackPressedCallback 未在 Bottom Sheet 对话框 fragment 中调用

java - Android viewpager下RelativeLayout

Android 折叠带有可滑动选项卡的操作栏

android - 如何禁用 FragmentStatePagerAdapter 上的滑动?

android - 在 Android 中使用 Glide 显示图像。看不到任何东西

Android:单击 View 时如何绘制边框