旋转屏幕后TabLayout状态无法持久化的问题排查
屏幕旋转后ViewPager2+TabLayout无法恢复选中Tab的问题
问题描述
尝试通过onSaveInstanceState()保存当前Tab位置,屏幕旋转后currentTabPosition的数值是正确的,但执行以下代码无法切换到对应Tab:
viewPager2.post(() -> { viewPager2.setCurrentItem(currentTabPosition, false); tabLayout.getTabAt(currentTabPosition); });
手动指定具体数值(比如1)时能正常切换到对应Tab。
问题代码
ConfigureFragment代码
public class ConfigureFragment extends Fragment { private TabLayout tabLayout; private ViewPager2 viewPager2; private ConfigureViewPageAdapter configureViewPageAdapter; private int currentTabPosition = 0; // Track the current selected tab position @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View fragmentView = inflater.inflate(R.layout.fragment_configure, container, false); tabLayout = fragmentView.findViewById(R.id.tabLayoutInConfigure); viewPager2 = fragmentView.findViewById(R.id.viewPagerInConfigure); configureViewPageAdapter = new ConfigureViewPageAdapter(requireActivity()); viewPager2.setAdapter(configureViewPageAdapter); String[] titles = new String[]{"Activity","Sensors"}; new TabLayoutMediator(tabLayout,viewPager2,((tab, position) -> {tab.setText(titles[position]);})).attach(); if(savedInstanceState!=null){ currentTabPosition = savedInstanceState.getInt("currentTabPosition"); Log.d("ADDD",currentTabPosition+"inside"); } Log.d("ADDD",currentTabPosition+"Outside"); viewPager2.post(() -> { viewPager2.setCurrentItem(currentTabPosition, false); tabLayout.getTabAt(currentTabPosition); }); // Inflate the layout for this fragment return fragmentView; } @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); // Save the current selected tab position outState.putInt("currentTabPosition", tabLayout.getSelectedTabPosition()); } @Override public void onViewStateRestored(@Nullable Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); } }
ConfigureViewPageAdapter代码
package com.hasanur.realtimehar.Adapter; import androidx.annotation.NonNull; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.viewpager2.adapter.FragmentStateAdapter; import com.hasanur.realtimehar.ActivityConfigureFragment; import com.hasanur.realtimehar.SensorConfigureFragment; import java.util.ArrayList; public class ConfigureViewPageAdapter extends FragmentStateAdapter { private ArrayList<Fragment> fragmentArrayList = new ArrayList<Fragment>(); public ConfigureViewPageAdapter(@NonNull FragmentActivity fragmentActivity) { super(fragmentActivity); add(new ActivityConfigureFragment()); add(new SensorConfigureFragment()); } @NonNull @Override public Fragment createFragment(int position) { return fragmentArrayList.get(position); } @Override public int getItemCount() { return fragmentArrayList.size(); } public void add(Fragment fragment){ fragmentArrayList.add(fragment); } }
解决方案
原因分析
TabLayoutMediator在ViewPager2设置适配器后会自动同步初始状态,此时还未恢复保存的Tab位置,后续调用setCurrentItem可能被Mediator的默认同步覆盖。tabLayout.getTabAt(currentTabPosition)仅获取Tab对象,没有执行选中操作,属于无效代码。
修复步骤
- 将恢复Tab位置的逻辑移到
onViewStateRestored方法中,该方法是专门用于恢复视图状态的回调,执行时机晚于onCreateView,能确保ViewPager2和TabLayout完全初始化。 - 移除无效的
tabLayout.getTabAt调用,ViewPager2.setCurrentItem执行后,TabLayoutMediator会自动同步Tab的选中状态。
修改后的ConfigureFragment代码
public class ConfigureFragment extends Fragment { private TabLayout tabLayout; private ViewPager2 viewPager2; private ConfigureViewPageAdapter configureViewPageAdapter; private int currentTabPosition = 0; // Track the current selected tab position @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View fragmentView = inflater.inflate(R.layout.fragment_configure, container, false); tabLayout = fragmentView.findViewById(R.id.tabLayoutInConfigure); viewPager2 = fragmentView.findViewById(R.id.viewPagerInConfigure); configureViewPageAdapter = new ConfigureViewPageAdapter(requireActivity()); viewPager2.setAdapter(configureViewPageAdapter); String[] titles = new String[]{"Activity","Sensors"}; new TabLayoutMediator(tabLayout,viewPager2,((tab, position) -> {tab.setText(titles[position]);})).attach(); if(savedInstanceState!=null){ currentTabPosition = savedInstanceState.getInt("currentTabPosition"); Log.d("ADDD",currentTabPosition+"inside"); } Log.d("ADDD",currentTabPosition+"Outside"); // Inflate the layout for this fragment return fragmentView; } @Override public void onSaveInstanceState(@NonNull Bundle outState) { super.onSaveInstanceState(outState); // Save the current selected tab position outState.putInt("currentTabPosition", tabLayout.getSelectedTabPosition()); } @Override public void onViewStateRestored(@Nullable Bundle savedInstanceState) { super.onViewStateRestored(savedInstanceState); // 在此处恢复Tab位置,确保视图与Mediator初始化完成 if(savedInstanceState!=null){ currentTabPosition = savedInstanceState.getInt("currentTabPosition"); viewPager2.setCurrentItem(currentTabPosition, false); } } }
额外优化
若仍存在问题,可添加ViewPager2页面变化监听,实时同步currentTabPosition,确保保存的位置准确:
// 在onCreateView中添加 viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() { @Override public void onPageSelected(int position) { super.onPageSelected(position); currentTabPosition = position; } });
内容的提问来源于stack exchange,提问作者Hasan Seam
相关产品推荐
相关产品推荐

