You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ViewPager2+TabLayout点击序号>3的Tab时跳转到最后一页问题求助

ViewPager2 + TabLayout 点击跳转异常问题

我在实现ViewPager2 + TabLayout组合功能时遇到异常:相同逻辑的Java代码运行正常,但Kotlin代码中,点击序号大于3的Tab时,ViewPager2会直接跳转到最后一页;滑动ViewPager2可正常显示对应页面,点击第1、2、3个Tab也能正常跳转。在Adapter中添加日志后,发现点击时会依次打印所有位置的信息。

Adapter类代码

class ViewPager2Adapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    FragmentStateAdapter(fragmentManager, lifecycle) {
    private val fragmentList: ArrayList<Fragment> = ArrayList<Fragment>()
    override fun createFragment(position: Int): Fragment {
        Log.e("TAG",position.toString() )
        return fragmentList[position]

    }

    fun addFragment(fragment: Fragment) {
        fragmentList.add(fragment)
    }

    override fun getItemCount(): Int {
        return fragmentList.size
    }

    override fun getItemViewType(position: Int): Int {
        return position
    }

    fun add(s: Fragment) {
        fragmentList.add(s)

    }
}

ViewPager初始化代码

fun setupTabLayout() {
       
        val home = activity as HomeDash

        val myAdapter = ViewPager2Adapter(this.getChildFragmentManager() , this.lifecycle)
        var  FragmentNameList:Array<String>
        
            myAdapter.addFragment(StatisticsFragment())
            myAdapter.addFragment(ApprovalFragment())
            myAdapter.addFragment(ProfessionalDetailsFragment())
            myAdapter.addFragment(PersonalDetailsFragment())
            myAdapter.addFragment(EducationalDetailsFragment())
            myAdapter.addFragment(BankDetailsFragmnt())
            myAdapter.addFragment(SalaryDetailsFragment())
            myAdapter.addFragment(LoanFragment())

             FragmentNameList = arrayOf(
                "Statistics",
                "Approval",
                "Professional Details",
                "Personal Details",
                "Educational Details",
                "Bank Details",
                "Salary Details",
                "Loan Details",
            )
        
        
        viewbinding.tabPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL)

        viewbinding.tabPager.setAdapter(myAdapter)


        TabLayoutMediator(viewbinding.fragmentTabLayout, viewbinding.tabPager) { tab, position ->
            tab.text = FragmentNameList[position]
            //viewbinding.tabPager.setCurrentItem(position, false)

        }.attach()


    }

日志输出

2023-10-23 17:00:01.125  3752-3752  TAG                     gen.reporting_mvvm                   E  0
2023-10-23 17:00:02.534  3752-3752  TAG                     gen.reporting_mvvm                   E  1
2023-10-23 17:00:02.550  3752-3752  TAG                     gen.reporting_mvvm                   E  On create 
2023-10-23 17:00:02.876  3752-3764  System                  gen.reporting_mvvm                   W  A resource failed to call close. 
2023-10-23 17:00:02.916  3752-3752  RecyclerView            gen.reporting_mvvm                   W  No adapter attached; skipping layout
2023-10-23 17:00:03.183  3752-3752  RecyclerView            gen.reporting_mvvm                   W  No adapter attached; skipping layout
2023-10-23 17:00:03.187  3752-3752  View                    gen.reporting_mvvm                   D  [ANR Warning]onLayout time too long, this =androidx.recyclerview.widget.RecyclerView{9f12e4b VFED..... ......ID 54,48-1026,1579 #7f0a00a1 app:id/RecyclerApproval}time =629 ms
2023-10-23 17:00:03.187  3752-3752  View                    gen.reporting_mvvm                   D  [ANR Warning]onLayout time too long, this =androidx.constraintlayout.widget.ConstraintLayout{cdc028 V.E...... ......ID 0,0-1080,1611}time =630 ms
2023-10-23 17:00:03.187  3752-3752  View                    gen.reporting_mvvm                   D  [ANR Warning]onLayout time too long, this =android.widget.FrameLayout{f173141 V.E...... ......ID 1080,0-2160,1611 #3}time =630 ms
2023-10-23 17:00:03.189  3752-3752  TAG                     gen.reporting_mvvm                   E  2
2023-10-23 17:00:04.067  3752-3752  Looper                  gen.reporting_mvvm                   W  PerfMonitor longMsg : seq=1367 plan=17:00:02.518 late=12ms wall=1533ms h=android.view.Choreographer$FrameHandler c=android.view.Choreographer$FrameDisplayEventReceiver procState=-1
2023-10-23 17:00:04.067  3752-3752  Looper                  gen.reporting_mvvm                   W  PerfMonitor doFrame : time=1533ms vsyncFrame=0 latency=12ms procState=-1 historyMsgCount=2
2023-10-23 17:00:04.071  3752-3752  Choreographer           gen.reporting_mvvm                   I  Skipped 138 frames!  The application may be doing too much work on its main thread.
2023-10-23 17:00:04.158  3752-3752  TAG                     gen.reporting_mvvm                   E  3
2023-10-23 17:00:04.620  3752-3752  TAG                     gen.reporting_mvvm                   E  4
2023-10-23 17:00:05.554  3752-3752  TAG                     gen.reporting_mvvm                   E  5
2023-10-23 17:00:06.027  3752-3752  TAG                     gen.reporting_mvvm                   E  6
2023-10-23 17:00:06.872  3752-3752  TAG                     gen.reporting_mvvm                   E  7

问题原因与解决方法

原因

问题出在重写的getItemViewType方法:返回position作为ViewType后,FragmentStateAdapter的内部回收重建逻辑被打乱,当页面数量超过ViewPager2默认的预加载阈值后,TabLayoutMediator的位置映射关系出现异常,导致点击后跳转错误。

解决步骤

  1. 删除getItemViewType重写代码:FragmentStateAdapter默认已实现合适的ViewType管理逻辑,无需手动返回position。
  2. 清理Adapter冗余代码:移除重复的add方法,统一使用addFragment。

修改后的Adapter代码:

class ViewPager2Adapter(fragmentManager: FragmentManager, lifecycle: Lifecycle) :
    FragmentStateAdapter(fragmentManager, lifecycle) {
    private val fragmentList = ArrayList<Fragment>()

    override fun createFragment(position: Int): Fragment {
        Log.e("TAG", position.toString())
        return fragmentList[position]
    }

    fun addFragment(fragment: Fragment) {
        fragmentList.add(fragment)
    }

    override fun getItemCount(): Int {
        return fragmentList.size
    }
}
  1. 额外优化建议:日志显示主线程存在卡顿和ANR警告,建议给Fragment添加懒加载逻辑,避免一次性在主线程创建大量Fragment导致性能问题。

内容的提问来源于stack exchange,提问作者Paras Rajora

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 18:14:51