在ViewPager中具有StaggeredGridLayoutManager的RecyclerView,在返回片段时会自动排列项目 [英] RecyclerView with StaggeredGridLayoutManager in ViewPager, arranges items automatically when going back to fragment

本文介绍了在ViewPager中具有StaggeredGridLayoutManager的RecyclerView,在返回片段时会自动排列项目的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Google Advanced Sample(

在转到下一个片段之前:

,然后返回片段:

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

请考虑:

  • 如果使用导航组件更改片段,则存在此问题.如果使用 supportFragmentManager.beginTransaction()启动片段,或者启动另一个活动,然后转到该片段,就可以了.但是如果我使用导航组件导航到另一个片段,则存在此问题.(可能是由于重新创建了片段)

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

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

  • 如果同时使用ViewPager2和FragmentStatePagerAdapter,则没有区别

  • 我尝试防止碎片的重新创建(通过此解决方案),但没有解决.

更新:您可以从以下位置克隆有此问题的项目:此处

解决方案

使用导航组件 + ViewPager + StaggeredGridLayoutManager 时,错误的 Fragment 的过程中已返回> recyclerView.computeVerticalScrollOffset().

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

  class TestFragment:Fragment(R.layout.fragment_test){私有val testListAdapter:由惰性{TestListAdapter()}私人var layoutManagerState:可拆分?=空重写fun onViewCreated(view:View,savedInstanceState:Bundle?){super.onViewCreated(view,savedInstanceState)postListView.apply {layoutManager = StaggeredGridLayoutManager(2,StaggeredGridLayoutManager.VERTICAL).申请 {gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_MOVE_ITEMS_BETWEEN_SPANS}setHasFixedSize(true)适配器= testListAdapter}testListAdapter.stateRestorationPolicy = RecyclerView.Adapter.StateRestorationPolicy.PREVENT}覆盖fun onPause(){saveLayoutManagerState()super.onPause()}重写fun onViewStateRestored(savedInstanceState:Bundle?){super.onViewStateRestored(savedInstanceState)restoreLayoutManagerState()}私人乐趣restoreLayoutManagerState(){layoutManagerState?.let {postListView.layoutManager?.onRestoreInstanceState(it)}}私人乐趣saveLayoutManagerState(){layoutManagerState = postListView.layoutManager?.onSaveInstanceState()}} 

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

I am using Navigation component in my App, using google Advanced Sample(here). my problem is when going back to a fragment, the scrolling position does not lost but it rearranges items and moves highest visible items so that top of those item align to top of recyclerview. please see this:

before going to next fragment:

and after back to fragment:

this problem is matter because some times clicked item goes down and not seen until scroll down. how to prevent this behavior?

please consider:

  • this problem exist if using navigation component to change fragment. if start fragment using supportFragmentManager.beginTransaction() or start another activity and then go to this fragment it is OK. but if I navigate to another fragment using navigation component this problem is exist.(maybe because of recreating fragment)

  • also this problem exist if using fragment in ViewPager. i.e recyclerView is in a fragment that handle with ViewPagerAdapter and viewPager is in HomeFragment that opened with Navigation component. if recyclerView is in HomeFragment there is no problem.

  • no problem with LinearLayoutManager. only with StaggeredGridLayoutManager.

  • there is not difference if using ViewPager2 and also FragmentStatePagerAdapter

  • I try to prevent recreate of fragment(by this solution) but not solved.

UPDATE: you can clone project with this problem from here

解决方案

When using Navigation Component + ViewPager + StaggeredGridLayoutManager, wrong recyclerView.computeVerticalScrollOffset() has been returned during Fragment recreate.

In general, all layout managers bundled in the support library already know how to save and restore scroll position, but in this case, we had to take responsibility for this.

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

Source code: https://github.com/dautovicharis/MyStaggeredListSample/tree/q_65539771

这篇关于在ViewPager中具有StaggeredGridLayoutManager的RecyclerView,在返回片段时会自动排列项目的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆