问题描述
|
我将Android应用程序移植到蜂窝上,为了使用片段,我做了很大的重构。在以前的版本中,当我按下“主页”按钮时,我曾经做过一个“ 0”以重置后退纸叠。
现在我的应用只是一个带有多个片段的Activity,因此当我按下Home按钮时,我只是替换了其中的一个片段。如何在不使用
ACTIVITY_CLEAR_TOP
标志的情况下清除stack栈?
解决方法
我在这里贴了类似的东西
根据约阿希姆的回答,来自黛安·哈克伯恩(Dianne Hackborn):
http://groups.google.com/group/android-developers/browse_thread/thread/d2a5c203dad6ec42
我最终只是使用:
FragmentManager fm = getActivity().getSupportFragmentManager();
for(int i = 0; i < fm.getBackStackEntryCount(); ++i) {
fm.popBackStack();
}
但是同样可以使用以下方法:
((AppCompatActivity)getContext()).getSupportFragmentManager().popBackStack(String name,FragmentManager.POP_BACK_STACK_INCLUSIVE)
这会将所有状态弹出到指定状态。然后,您可以将片段替换为所需的片段
, 为@Warpzit的评论提供答案,并使其他人更容易找到。
采用:
fragmentManager.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
, 充分尊重所有有关方面;我很惊讶地看到你们中有多少人可以通过简单的操作清除整个碎片
fm.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
根据Android文档(关于name
参数-所主张的工作建议中的\“ null \”)。
如果为null,则仅弹出最高状态
现在,我的确意识到我对您的特定实现缺乏了解(例如,在给定的时间点,您在后台堆栈中有多少个条目),但是我希望所有的钱都花在接受的答案上,希望得到一个好的结果在更广泛的设备和供应商中定义的行为:
(供参考,与此同时)
FragmentManager fm = getFragmentManager(); // or \'getSupportFragmentManager();\'
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
fm.popBackStack();
}
, 接受的答案对我来说还不够。我不得不使用:
FragmentManager fm = getSupportFragmentManager();
int count = fm.getBackStackEntryCount();
for(int i = 0; i < count; ++i) {
fm.popBackStackImmediate();
}
, 为我工作,不使用循环的简单方法:
FragmentManager fragmentManager = getSupportFragmentManager();
//this will clear the back stack and displays no animation on the screen
fragmentManager.popBackStackImmediate(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
, 清除没有循环的堆栈
String name = getSupportFragmentManager().getBackStackEntryAt(0).getName();
getSupportFragmentManager().popBackStack(name,FragmentManager.POP_BACK_STACK_INCLUSIVE);
其中name是addToBackStack()参数
getSupportFragmentManager().beginTransaction().
.replace(R.id.container,fragments.get(titleCode))
.addToBackStack(name)
, 我只想补充:-
使用以下命令从堆栈弹出
fragmentManager.popBackStack()
只是要从事务中删除碎片,而无法从屏幕上删除碎片。
因此,理想情况下,它可能对您不可见,但是可能有两个或三个片段彼此堆叠,并且在按回车键时,UI可能看起来很杂乱,堆叠。
仅举一个简单的例子:
假设您有一个fragmentA,它使用fragmentmanager.replace()加载Fragmnet B,然后执行addToBackStack来保存该事务。
所以流程是:-
步骤1-> FragmentA-> FragmentB(我们移至FragmentB,但是Fragment A在背景中,不可见)。
现在,您在fragmentB中进行一些工作,然后按“保存”按钮,保存后,该按钮应返回至fragmentA。
步骤2->保存FragmentB,然后返回FragmentA。
步骤3->所以常见的错误是...在片段B中,我们将使用片段A执行片段Manager.replace()片段B。
但是实际上发生了什么,我们再次加载Fragment A,代替FragmentB。因此,现在有两个FragmentA(一个来自STEP-1,一个来自此STEP-3)。
FragmentsA的两个实例彼此堆叠,这可能不可见,但在那里。
因此,即使我们确实通过上述方法清除了后栈,事务也会被清除,但不会清除实际的碎片。
因此,理想情况下,在这种情况下,只需按一下保存按钮,只需执行fm.popBackStack()或fm.popBackImmediate()即可返回fragmentA。
因此,正确的Step3-> fm.popBackStack()返回到已经在内存中的fragmentA。
, 阅读文档并研究片段ID是什么,它似乎只是堆栈索引,因此可行:
fragmentManager.popBackStackImmediate(0,FragmentManager.POP_BACK_STACK_INCLUSIVE);
零(0
)是堆栈的底部,因此弹出时将其包括在内会清除堆栈。
CAVEAT:尽管上面的代码在我的程序中有效,但我还是有些犹豫,因为FragmentManager文档从不实际声明id是堆栈索引。确实是这样,我的所有调试日志都没有,但是在某些特殊情况下不是吗?任何人都可以以一种或另一种方式确认这种情况吗?如果是这样,那么以上是最佳解决方案。如果没有,这是替代方案:
while(fragmentManager.getBackStackEntryCount() > 0) { fragmentManager.popBackStackImmediate(); }
,
只需使用此方法,然后传递Context&Fragment标签即可,我们需要删除该标签。
用法
clearFragmentByTag(context,FragmentName.class.getName());
public static void clearFragmentByTag(Context context,String tag) {
try {
FragmentManager fm = ((AppCompatActivity) context).getSupportFragmentManager();
for (int i = fm.getBackStackEntryCount() - 1; i >= 0; i--) {
String backEntry = fm.getBackStackEntryAt(i).getName();
if (backEntry.equals(tag)) {
break;
} else {
fm.popBackStack();
}
}
} catch (Exception e) {
System.out.print(\"!====Popbackstack error : \" + e);
e.printStackTrace();
}
}
, 嗨〜我找到了一个更好的解决方案,来自:https://gist.github.com/ikew0ng/8297033
/**
* Remove all entries from the backStack of this fragmentManager.
*
* @param fragmentManager the fragmentManager to clear.
*/
private void clearBackStack(FragmentManager fragmentManager) {
if (fragmentManager.getBackStackEntryCount() > 0) {
FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0);
fragmentManager.popBackStack(entry.getId(),FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
}
, 我这样工作:
public void showHome() {
getHandler().post(new Runnable() {
@Override
public void run() {
final FragmentManager fm = getSupportFragmentManager();
while (fm.getBackStackEntryCount() > 0) {
fm.popBackStackImmediate();
}
}
});
}
,它对我有用,请尝试以下方法:
public void clearFragmentBackStack() {
FragmentManager fm = getSupportFragmentManager();
for (int i = 0; i < fm.getBackStackEntryCount() - 1; i++) {
fm.popBackStack();
}
}
, private void clearBackStack(){
SupportFragmentManaer fm = getSupportFragmentManager();
fm.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
}
调用此方法将非常简洁。
无需循环。
如果您在片段中使用动画,它将不会显示太多动画。但是使用循环会。
, private boolean removeFragFromBackStack() {
try {
FragmentManager manager = getSupportFragmentManager();
List<Fragment> fragsList = manager.getFragments();
if (fragsList.size() == 0) {
return true;
}
manager.popBackStack(null,FragmentManager.POP_BACK_STACK_INCLUSIVE);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}