ViewPager2:如何防止创建的碎片干扰滑动动画?

3

我有一个带有FragmentStateAdapter和离屏页面限制为1的ViewPager2

viewPager.setAdapter(new MyFragmentStateAdapter(this));
viewPager.setOffscreenPageLimit(1);

public class MyFragmentStateAdapter extends FragmentStateAdapter {

    MyFragmentStateAdapter(@NonNull Fragment fragment) {
        super(fragment);
    }

    @NonNull
    @Override
    public Fragment createFragment(int position) {
        return new ItemFragment(position);
    }

    @Override
    public int getItemCount() {
        return 15;
    }

}

发生了什么:

  • 我观察到每次在视图页面上滑动时,都会有一个卡顿的滑动动画。所以我开始调查它。

我的发现:

  • 我发现在ViewPager2中,新的屏幕外片段是在滑动手势的开始时创建的(而现在已被弃用的ViewPager是在滑动手势结束时创建的)。
  • 无论setOffscreenPageLimit的值是多少(除非您的意图是一次加载所有片段),每当视图页面需要创建新的屏幕外片段时都会出现这个问题。

为什么这是个问题:

  • 这意味着片段的创建总是会干扰滑动动画,基本上破坏了setOffscreenPageLimit的目的(但是,如果您的片段非常轻量级,您可能不会注意到问题)。

问题:

  • 是否有一种方法可以强制ViewPager2与FragmentStateAdapter在滑动手势结束时创建屏幕外片段(就像已弃用的ViewPager一样)?

你好 @jmart,你有找到解决方法吗?谢谢。 - Jack
@Jack 目前还没有,但我在问题跟踪器(https://issuetracker.google.com/issues/150626937)上开了一个问题,并且已经被接受,所以我想我们必须等待新版本的ViewPager2发布。 - jmart
谢谢你告诉我。 - Jack
是的,我也遇到了这个问题。每次我滑动时都会出现卡顿,数据也会在我滑动时加载,所以显然它会“卡住”。 - Udayaditya Barua
1
@jmart,你找到了这个问题的解决方案吗?我目前通过在调用notifyDataSetChanged()时使用带有300ms延迟的postDelayed-Handler来规避此问题,但这对我来说似乎像是一个hack。下面的onPageScrollStateChanged解决方案在我的情况下没有任何区别。我可以清楚地看到,在UI线程上刷新数据(notifyDataSetChanged)时,滑动动画开始(片段#1->#2),然后很快被片段中断(#3)。在Perfetto跟踪中。 - Patrick
@Patrick 还没有。我仍在使用原始的ViewPager。我在问题跟踪器上开了一个问题,但标记为“已分配”,但优先级较低。 - jmart
1个回答

2

我的解决方案:

        view_pager.registerOnPageChangeCallback(object :
        ViewPager2.OnPageChangeCallback() {
        override fun onPageScrollStateChanged(state: Int) {
            super.onPageScrollStateChanged(state)
            when (state) {
                SCROLL_STATE_IDLE -> {
                    view_pager.offscreenPageLimit = 1
                }
                SCROLL_STATE_DRAGGING -> {
                    view_pager.offscreenPageLimit = OFFSCREEN_PAGE_LIMIT_DEFAULT
                }
            }
        }
    })
    view_pager.offscreenPageLimit = 1

SCROLL_STATE_DRAGGING 时,将 offscreenPageLimit = OFFSCREEN_PAGE_LIMIT_DEFAULT 设置为防止在滑动手势上创建下一个片段。在滑动手势之后设置 offscreenPageLimit = 1,以创建下一个片段。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接