繁体   English   中英

ViewPager2 默认位置

[英]ViewPager2 default position

我正在使用 ViewPager2 创建幻灯片。 例如,幻灯片有 3 个项目,我想在活动打开时显示第二个项目。 我使用setCurrentItem(int item, boolean smoothScroll)方法,但它不起作用,也没有任何反应。 我怎样才能实现它?

viewPager.adapter = adapter
viewPager.setCurrentItem(1, true)

我认为更简单更可靠的解决方法是推迟到下一个运行周期而不是不安全的延迟,例如

viewPager.post {
  viewPager.setCurrentItem(1, true)
}

setCurrentItem(int item, boolean smoothScroll)正常工作在ViewPager但在ViewPager2它不会按预期工作。 最后,我通过将setCurrentItem(int item, boolean smoothScroll ) 方法添加到这样的延迟中来解决这个问题:

Handler().postDelayed({
     view.viewPager.setCurrentItem(startPosition, false)
}, 100)

不要使用计时器,您会遇到很多可能的状态,其中用户的手机速度很慢,实际上运行时间超过 100 毫秒,而且,您也不希望计时器太慢而变得荒谬不可靠。

下面我们执行以下操作,我们为 ViewTreeObserver 设置一个侦听器,并等待在 ViewPager2 的 RecyclerView 中布置一定数量的子项(它是内部工作的)。 一旦我们确定已经布置了 x 个项目,我们就开始我们的无动画滚动以从该位置开始。

val recyclerView = (Your ViewPager2).getChildAt(0)

recyclerView.apply {
   val itemCount = adapter?.itemCount ?: 0
   if(itemCount >= #(Position you want to scroll to)) {
      viewTreeObserver.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener {
      override fun onGlobalLayout() {
         viewTreeObserver.removeOnGlobalLayoutListener(this)

         // False for without animation scroll
         (Your ViewPager2).scrollToPosition(#PositionToStartAt, false)
      }
   }
}

首先,我认为接受的答案(@hosseinAmini 的)是建议使用延迟来解决问题的答案,这是一种耻辱。 您应该首先寻找假定的错误是由什么引起的,而不是相信这样的不合理的解决方案。

@Rune 的提议是正确的; 所以我在回答中引用了他们的代码:

 viewPager.post { viewPager.setCurrentItem(1, true) }

我唯一要争论的是上述人认为他们的解决方案只是在下一个运行周期中推迟该 lambda 的执行。 这不会使任何有问题的东西正常工作。 相反,它实际所做的是将 lambda 的执行推迟到视图附加到窗口后,这意味着它也已添加到父视图中。 实际上,在附加到窗口之前更改当前的ViewPager2项目似乎存在问题。 支持这一说法的一些证据如下:

  • 使用任何一个Handler都不会有效地工作。

     Handler(Looper.getMainLooper()).post { viewPager.setCurrentItem(1, true) // Not working properly }

    从理论的角度来看,由于ViewPager2被附加到获取主ViewPager2消息队列中的优先级的窗口,它可能会偶然工作,但这不应该被依赖,因为不能保证它会工作(它是更有可能它不会),如果它甚至被证明是有效的,运行多个测试的进一步调查应该会让我的观点变得清晰。

  • View.handler获取null ,这意味着该视图尚未附加到任何窗口。

     View.handler // = null

    尽管 Android UI 绑定到主循环器,它总是唯一对应于主线程——因此也称为 UI 线程,一个奇怪的设计选择站在处理程序中,直到它们附加到窗口时才与每个视图相关联。 这可能是因为视图无法在主线程上调度任何工作,而它们不是层次结构的一部分,这可能在实现调度视图更新但不知道它们的生命周期的视图控制器时变得有用(在在这种情况下,它将使用View的处理程序(如果有),或者只是跳过调度它要执行的任何操作(如果没有)。

编辑:

此外,@josias 在评论中指出,使用起来会更清楚:

viewPager.doOnAttach {
    viewPager.setCurrentItem(1, true)
}

谢谢你的建议! 它更好地表达了实际意图,而不是依赖于View.post方法的行为。

mViewPager.setCurrentItem(1, true); --->正如你上面写的那样就足够了

这应该有效,有疑问,只需检查您的位置:

        @Override
        public void onPageSelected(int i) {
            if (LOG_DEBUG) Log.v(TAG, " ++++++++    onPageSelected:  " + i);
            mViewPager.setCurrentItem(i);
            //TODO You can use this position: to write other dependent logic

        }

并检查

PagerAdapter 中的 getItem(int position)

或者粘贴您的代码。

如上所述,您必须在ViewPager2上使用setCurrentItem(position, smoothScroll)方法才能显示所选项目。 为了让它工作,你必须定义一个回调,这是一个例子:

ViewPager2.OnPageChangeCallback callback = new ViewPager2.OnPageChangeCallback() {
    @Override
    public void onPageSelected(int position) {
        super.onPageSelected(position);
    }
};

然后你必须按如下方式注册它:

viewPager.registerOnPageChangeCallback(callback);

也不要忘记注销它:

viewPager.unregisterOnPageChangeCallback(callback);

当您调用setCurrentItem(position)方法时,它将从传递参数的回调中调用onPageSelected(int position)方法,然后将调用FragmentStateAdapter类中的createFragment(int position)方法以显示您的片段

我尝试在Handler().dely() viewPager2.post{} Handler().dely()viewPager2.post{}甚至' viewPager2.get(0).post更改 viewpager2 页面也对我不起作用,我将ViewPagerFragmentStateAdapterTablayout一起使用。

对我RecylerView在手动FragmentStateAdapter绑定yourViewPager2View.adapter更改RecylerViewViewPager2的位置:

 (yourViewPager2View[0] as RecyclerView).scrollToPosition(moveToTabNumber)

为什么

我的问题是onCreateFragment(position:Int):Fragmeet FragmentStateAdapter onCreateFragment(position:Int):Fragmeet函数总是从0 位置开始片段,无论我设置页面的是什么 pageNumber

viewPager.setCurrentItem = pageNumber

我检查那里,它被称为在FragmentStateAdapter这就是所谓的FragmentStateAdapter

onBindViewHolder(final @NonNull FragmentViewHolder holder, int position)`

所以我需要的只是强制onBindViewHolder使用我想要的页码调用onCreateFragment(position:Int)

尝试使用viewPager.setCurrentItem(1, false) 那个'false'是关于smoothScroll,当你的活动刚打开时你不能平滑滚动你的viewPager2。 在 onViewCreated() 方法中的片段上对其进行了测试,它也不适用于“true”,但适用于“false”

首先,您需要在您想要的任何侦听器或按钮下初始化 Main 活动,然后在此之后您需要放置此 Line.. 这里 MainActvity 是您正在使用的 Viewpager 主类,2 是您要移动的位置

 MainActivity main = (MainActivity ) mContext;
    main.selectTab(2, true);

我的回答现在可能没有帮助,但我认为发布我的经验没有坏处,我只是使用 ViewPager 和 ViewPager2 来解决这个问题,并通过更改一些行代码顺序意外地解决了它。

这是 ViewPager 的(java)解决方案:

    reviewWordViewPager.addOnPageChangeListener(changeListener);
    reviewWordViewPager.setCurrentItem(viewPosition, true/false);
    reviewWordTabIndicator.setupWithViewPager(reviewWordViewPager, true);

ViewPager2 的(Java)解决方案:

wordViewPager.registerOnPageChangeCallback(viewPager2OnPageChangeCallback);
wordViewPager.setCurrentItem(vpPosition, true/false);
new TabLayoutMediator(tabIndicator, wordViewPager,
            ((tab, position) -> tab.setText(viewPagerTitle[position]))).attach();

我没有查找ViewPager2是否需要ViewPager中使用的以下旧代码

    @Override
public int getItemPosition(@NonNull Object object) {
    // refresh all fragments when data set changed
    return POSITION_NONE;
}

但令人惊讶的是,在 ViewPager2 中不需要它来解决我一直遇到的问题,希望它可以帮助其他人

如果您使用context.startActivity启动新活动wordViewPager.setCurrentItem(item, smoothScroll)onResume函数中使用wordViewPager.setCurrentItem(item, smoothScroll)返回上次选择的选项卡,然后再开始新活动,您只需保存 ViewPager/ViewPager2 位置,如vpPisition = wordViewPager.getCurrentItem(); onStop函数中。

vpPisition是一个全局变量。

我遇到了同样的问题。 在我的情况下,我默认使 viewPager2 Gone 消失,直到网络请求成功,我通过在使 viewPager2 可见后设置 CurrentItem 来修复它。

为@Daniel Kim,但为 Java 版本

RecyclerView rvOfViewPager2 = (RecyclerView) viewPager2.getChildAt(0);
    rvOfViewPager2.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener()
    {
        @Override
        public void onGlobalLayout()
        {
            rvOfViewPager2.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            viewPager2.setCurrentItem(currentTabId, false);
        }
    });

我注意到如果您选择不为其设置动画,它在最初创建视图时工作正常。

viewPager2.setCurrentItem(index, false)

根据您的用例,这通常很好 - 这个初始/默认项目可能不需要动画。

暂无
暂无

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

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