Fragment回退栈异常:从Fragment3返回时覆盖Fragment1问题求助
Fragment返回重叠问题解决方案
问题场景
导航逻辑:Fragment1(根Fragment)→ Fragment2(添加至回退栈)→ Fragment3(未添加至回退栈)
需求:进入Fragment3时隐藏Fragment2,点击返回键直接回到Fragment1
异常:点击Fragment3的返回键后,Fragment3与Fragment1重叠显示
涉及代码
打开Fragment1的代码
FragmentManager fragmentManager = getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_right); fragmentTransaction.add(R.id.abbcHomeFragmentContainer, new FragmentHomeAbbc(), null); //fragmentTransaction.addToBackStack(null); fragmentTransaction.commit();
从Fragment1打开Fragment2的代码
FragmentListOfBankAbbc fragment= new FragmentListOfBankAbbc(); fragment.setArguments(bundle); if (getActivity()!=null){ FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_right); fragmentTransaction.replace(R.id.abbcHomeFragmentContainer, fragment, null); fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); } else { Toast.makeText(getContext(), "Something went wrong (#201)", Toast.LENGTH_SHORT).show(); }
从Fragment2打开Fragment3的代码
private void funOpenFragments(Fragment fragment, Bundle bundle){ fragment.setArguments(bundle); if (getActivity()!=null){ FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_right); fragmentTransaction.replace(R.id.abbcHomeFragmentContainer, fragment, null); //fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); } else { Toast.makeText(getContext(), "Something went wrong (#202)", Toast.LENGTH_SHORT).show(); } }
问题原因
从Fragment2打开Fragment3时,使用replace且未添加至回退栈,此时Fragment2被移除,但回退栈中仍保留着「Fragment1→Fragment2」的切换记录。点击返回键时,系统会执行回退栈的上一步操作:将Fragment1恢复显示,但Fragment3未被加入回退栈,不会被移除,最终导致两者重叠。
解决方案
方案一:弹出回退栈后替换为Fragment3
修改打开Fragment3的方法,先弹出回退栈中Fragment2的切换记录,再替换为Fragment3:
private void funOpenFragments(Fragment fragment, Bundle bundle){ fragment.setArguments(bundle); if (getActivity()!=null){ FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); // 立即弹出回退栈顶部的Fragment2切换记录 fragmentManager.popBackStackImmediate(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_right); fragmentTransaction.replace(R.id.abbcHomeFragmentContainer, fragment, null); fragmentTransaction.commit(); } else { Toast.makeText(getContext(), "Something went wrong (#202)", Toast.LENGTH_SHORT).show(); } }
说明:popBackStackImmediate()会清除回退栈中Fragment2的切换记录,此时回退栈仅保留Fragment1的状态。点击返回键时,直接从Fragment3回到Fragment1,无重叠问题。
方案二:用Hide/Show控制Fragment状态(保留Fragment实例)
如果需要保留Fragment2实例仅隐藏它,可修改导航逻辑:
- 从Fragment1打开Fragment2时,改用
hide+add替代replace - 打开Fragment3时,隐藏Fragment2并弹出回退栈记录
修改从Fragment1打开Fragment2的代码
FragmentListOfBankAbbc fragment= new FragmentListOfBankAbbc(); fragment.setArguments(bundle); if (getActivity()!=null){ FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_right); // 隐藏当前显示的Fragment1,添加Fragment2 fragmentTransaction.hide(fragmentManager.findFragmentById(R.id.abbcHomeFragmentContainer)); fragmentTransaction.add(R.id.abbcHomeFragmentContainer, fragment, null); fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); } else { Toast.makeText(getContext(), "Something went wrong (#201)", Toast.LENGTH_SHORT).show(); }
修改从Fragment2打开Fragment3的代码
private void funOpenFragments(Fragment fragment, Bundle bundle){ fragment.setArguments(bundle); if (getActivity()!=null){ FragmentManager fragmentManager = getActivity().getSupportFragmentManager(); // 弹出回退栈中Fragment2的切换记录 fragmentManager.popBackStackImmediate(); FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); fragmentTransaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_right); // 隐藏当前显示的Fragment2,添加Fragment3 fragmentTransaction.hide(fragmentManager.findFragmentById(R.id.abbcHomeFragmentContainer)); fragmentTransaction.add(R.id.abbcHomeFragmentContainer, fragment, null); fragmentTransaction.commit(); } else { Toast.makeText(getContext(), "Something went wrong (#202)", Toast.LENGTH_SHORT).show(); } }
说明:通过hide/add保留Fragment实例,同时清除回退栈中Fragment2的记录,返回时直接回到Fragment1,避免重叠。
内容的提问来源于stack exchange,提问作者TexD
相关产品推荐
相关产品推荐

