Android ViewPager2绑定TabLayout切换Fragment异常问题
问题原因
你遇到的Tab点击跳转异常核心是ViewPager2.OnPageChangeCallback的回调使用错误:
onPageScrolled是页面滑动过程中持续高频触发的回调,返回的position是滑动过程中当前左侧停靠的页面位置,不是最终要跳转的目标页位置:- 从左向右跳(从低position页点高position的Tab):滑动全程
onPageScrolled返回的都是起始页的position,你在这里反复执行tabLayout.selectTab(tabLayout.getTabAt(position)),相当于不断把Tab选中状态拽回起始页,直接打断跳转流程,表现为点击无响应 - 从右向左跳(从高position页点低position的Tab):滑动全程
onPageScrolled返回的刚好是目标页的position,所以看起来跳转正常 - 跨多页跳转时(比如Fragment1跳Fragment3),滑动过程中回调反复选中中间/起始Tab,直接拦截跳转,导致无法跨页跳转
- 从左向右跳(从低position页点高position的Tab):滑动全程
- 你的
PagerAdapter逻辑没有问题,不需要修改。
修复方案
- 移除
onPageScrolled中的Tab选中逻辑,Tab和ViewPager的选中状态同步必须放到onPageSelected回调中,这个回调只会在页面最终切换完成后触发一次,返回的是真正选中的目标页position - 增加简单的同步标记位,避免Tab选中和ViewPager跳转互相触发导致的死循环
替换MainActivity中Tab和ViewPager联动的代码段即可:
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout); tabLayout.addTab(tabLayout.newTab().setText("Camera")); tabLayout.addTab(tabLayout.newTab().setText("Chats")); tabLayout.addTab(tabLayout.newTab().setText("Status")); tabLayout.addTab(tabLayout.newTab().setText("Calls")); tabLayout.setTabGravity(TabLayout.GRAVITY_FILL); final ViewPager2 viewPager = (ViewPager2) findViewById(R.id.pager); viewPager.setOffscreenPageLimit(3); final PagerAdapter adapter = new PagerAdapter(getSupportFragmentManager(), getLifecycle()); viewPager.setAdapter(adapter); // 同步标记位,避免回调循环触发 final boolean[] isSyncing = {false}; tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener(){ @Override public void onTabSelected(TabLayout.Tab tab) { if (isSyncing[0]) return; isSyncing[0] = true; viewPager.setCurrentItem(tab.getPosition()); } @Override public void onTabUnselected(TabLayout.Tab tab) {} @Override public void onTabReselected(TabLayout.Tab tab) {} }); viewPager.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { isSyncing[0] = true; tabLayout.selectTab(tabLayout.getTabAt(position)); } @Override public void onPageScrollStateChanged(int state) { super.onPageScrollStateChanged(state); // 滑动停止后重置标记位 if (state == ViewPager2.SCROLL_STATE_IDLE) { isSyncing[0] = false; } } });
修改后所有Tab点击跳转、手势滑动、跨多页切换逻辑都会恢复正常。
内容的提问来源于stack exchange,提问作者Dua
相关产品推荐
相关产品推荐

