AHBottomNavigation初始不加载Fragment及切换后异常问题求助
看起来你遇到的两个问题都是Fragment初始化和状态管理的典型场景,我来帮你逐个拆解修复:
问题a:启动时FirstFragment未加载的原因及修复
你在createNavItems()里调用了bottomNavigation.setCurrentItem(0),但这行代码执行时,setOnTabSelectedListener还没绑定到导航栏上!AHBottomNavigation的setCurrentItem在监听器未设置时不会触发选中回调,导致启动时虽然底部导航显示选中了First,但对应的Fragment根本没被加载。
修复方案:
把setCurrentItem(0)移到设置监听器之后执行,确保回调能正常触发:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bottomNavigation = findViewById(R.id.bottom_navigation); this.createNavItems(); // 先绑定监听器 bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() { @Override public boolean onTabSelected(int position, boolean wasSelected) { // 原有逻辑保持不变 if (position==0) { FirstFragment firstFragment=new FirstFragment(); getSupportFragmentManager().beginTransaction().replace(R.id.content_id,firstFragment).commit(); }else if (position==1) { SecondFragment secondFragment=new SecondFragment(); getSupportFragmentManager().beginTransaction().replace(R.id.content_id, secondFragment).commit(); }else if (position==2) { ThirdFragment thirdFragment=new ThirdFragment(); getSupportFragmentManager().beginTransaction().replace(R.id.content_id,thirdFragment).commit(); }else{ FourthFragment fourthFragment=new FourthFragment(); getSupportFragmentManager().beginTransaction().replace(R.id.content_id,fourthFragment).commit(); } return true; } }); // 再设置当前选中项,此时会触发监听器加载Fragment bottomNavigation.setCurrentItem(0); } // 修改createNavItems方法,移除里面的setCurrentItem private void createNavItems(){ navigationAdapter = new AHBottomNavigationAdapter(this, R.menu.navigation); navigationAdapter.setupWithBottomNavigation(bottomNavigation); }
问题b:切换回FirstFragment后子Tab空白、滑动异常的原因及修复
每次切换到First时你都new FirstFragment(),这会销毁之前的Fragment实例并创建全新对象,导致ViewPager的状态完全丢失。另外,FirstFragment里的ViewPager使用了Activity的getSupportFragmentManager(),而嵌套在Fragment里的子Fragment必须使用子Fragment管理器(getChildFragmentManager()),否则会出现层级混乱,引发滑动卡顿、状态丢失的问题。
修复方案:
- 缓存Fragment实例,避免每次切换都创建新对象;
- 将FirstFragment里的FragmentManager替换为
getChildFragmentManager()。
第一步:在MainActivity中缓存Fragment
public class MainActivity extends AppCompatActivity{ private AHBottomNavigationAdapter navigationAdapter; private AHBottomNavigation bottomNavigation; // 用数组缓存四个Fragment实例 private Fragment[] fragments = new Fragment[4]; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); bottomNavigation = findViewById(R.id.bottom_navigation); this.createNavItems(); // 提前初始化所有Fragment,后续复用 fragments[0] = new FirstFragment(); fragments[1] = new SecondFragment(); fragments[2] = new ThirdFragment(); fragments[3] = new FourthFragment(); bottomNavigation.setOnTabSelectedListener(new AHBottomNavigation.OnTabSelectedListener() { @Override public boolean onTabSelected(int position, boolean wasSelected) { // 复用缓存的Fragment,不再每次new getSupportFragmentManager().beginTransaction() .replace(R.id.content_id, fragments[position]) .commit(); return true; } }); bottomNavigation.setCurrentItem(0); } private void createNavItems(){ navigationAdapter = new AHBottomNavigationAdapter(this, R.menu.navigation); navigationAdapter.setupWithBottomNavigation(bottomNavigation); } }
第二步:修改FirstFragment的ViewPager初始化逻辑
public class FirstFragment extends Fragment { public FirstFragment() { // Required empty public constructor } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { return inflater.inflate(R.layout.fragment_first, container, false); } @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); // 改用getChildFragmentManager()管理子Fragment,并且在onViewCreated中初始化更稳妥 ViewPager viewPager = view.findViewById(R.id.viewpager); FirstFragmentPagerAdapter adapter = new FirstFragmentPagerAdapter(getChildFragmentManager(), getContext()); viewPager.setAdapter(adapter); TabLayout tabLayout = view.findViewById(R.id.sliding_tabs); tabLayout.setupWithViewPager(viewPager); } // 可以移除onAttach的代码,getContext()在onViewCreated阶段已经可用 }
同时调整FirstFragmentPagerAdapter的构造逻辑,直接使用传入的FragmentManager:
public class FirstFragmentPagerAdapter extends FragmentPagerAdapter { private Context context; public FirstFragmentPagerAdapter(FragmentManager fm, Context mContext){ super(fm); context = mContext; } // 其余代码保持不变 }
这样修改后,两个问题都能解决:启动时FirstFragment会正常加载,切换回来时会复用之前的Fragment实例,ViewPager的状态和滑动功能也能完全恢复正常。
内容的提问来源于stack exchange,提问作者Paradox

