如何在导航到 Android 中的另一个片段后清除导航堆栈
How to clear navigation Stack after navigating to another fragment in Android
我正在使用 android 中的新 Navigation Architecture Component,但在移动到新片段后我无法清除导航堆栈。
示例:
我在 loginFragment 中,我希望在导航到主页片段时从堆栈中清除该片段,以便用户在按下后退按钮时不会返回到 loginFragment。
我正在使用简单的 NavHostFragment.findNavController(Fragment).navigate(R.id.homeFragment) 进行导航。
当前代码:
mAuth.signInWithCredential(credential)
.addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment);
} else {
Log.w(TAG, "signInWithCredential:failure", task.getException());
}
}
});
我尝试使用 NavOptions in the navigate(),但后退按钮仍将我送回 loginFragment
NavOptions.Builder navBuilder = new NavOptions.Builder();
NavOptions navOptions = navBuilder.setPopUpTo(R.id.homeFragment, false).build();
NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment, null, navOptions);
感谢
,我终于弄明白了
我必须将 .setClearTask(true) 指定为 NavOption。
mAuth.signInWithCredential(credential)
.addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Log.d(TAG, "signInWithCredential:success");
NavOptions.Builder navBuilder = new NavOptions.Builder();
NavOptions navOptions = navBuilder.setClearTask(true).build();
NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment,null,navOptions);
} else {
Log.w(TAG, "signInWithCredential:failure", task.getException());
}
}
});
注意:清除任务已弃用,官方描述为
This method is deprecated. Use setPopUpTo(int, boolean) with the id of the NavController's graph and set inclusive to true.
旧答案
如果您不想在代码中经历所有这些模糊,您可以简单地检查操作属性中 Launch Options
中的 Clear Task
。
编辑: 自 Android Studio 3.2 Beta 5 起,启动选项中不再显示清除任务 window,但您仍然可以使用它在导航的 XML 代码中,在 action 标签中,通过添加
app:clearTask="true"
首先,将属性 app:popUpTo='your_nav_graph_id'
和 app:popUpToInclusive="true"
添加到操作标签。
<fragment
android:id="@+id/signInFragment"
android:name="com.glee.incog2.android.fragment.SignInFragment"
android:label="fragment_sign_in"
tools:layout="@layout/fragment_sign_in" >
<action
android:id="@+id/action_signInFragment_to_usersFragment"
app:destination="@id/usersFragment"
app:launchSingleTop="true"
app:popUpTo="@+id/main_nav_graph"
app:popUpToInclusive="true" />
</fragment>
其次,导航到目的地,使用上述操作作为参数。
findNavController(fragment).navigate(
SignInFragmentDirections.actionSignInFragmentToUserNameFragment())
有关详细信息,请参阅 docs。
注意:如果您使用方法 navigate(@IdRes int resId)
进行导航,您将无法获得所需的结果。因此,我使用了方法 navigate(@NonNull NavDirections directions)
.
我认为您的问题具体涉及如何使用 Pop Behavior / Pop To / app:popUpTo(在 xml 中)
在文档中,
导航前弹出给定目的地。这将从返回堆栈中弹出所有 non-matching 个目的地,直到找到该目的地。
示例(简单的求职应用程序)
我的 start_screen_nav 图表是这样的:
startScreenFragment (start) -> loginFragment -> EmployerMainFragment
-> loginFragment -> JobSeekerMainFragment
如果我想导航到 EmployerMainFragment
并弹出所有 包括 startScreenFragment
那么代码将是:
<action
android:id="@+id/action_loginFragment_to_employerMainFragment"
app:destination="@id/employerMainFragment"
app:popUpTo="@+id/startScreenFragment"
app:popUpToInclusive="true" />
如果我想导航到 EmployerMainFragment
并弹出所有 排除 startScreenFragment
那么代码将是:
<action
android:id="@+id/action_loginFragment_to_employerMainFragment"
app:destination="@id/employerMainFragment"
app:popUpTo="@+id/startScreenFragment"/>
如果我想导航到 EmployerMainFragment
并弹出 loginFragment
但 不是 startScreenFragment
那么代码将是:
<action
android:id="@+id/action_loginFragment_to_employerMainFragment"
app:destination="@id/employerMainFragment"
app:popUpTo="@+id/loginFragment"
app:popUpToInclusive="true"/>
或
<action
android:id="@+id/action_loginFragment_to_employerMainFragment"
app:destination="@id/employerMainFragment"
app:popUpTo="@+id/startScreenFragment"/>
在我的例子中,我需要在打开新片段之前删除后台堆栈中的所有内容,所以我使用了这段代码
navController.popBackStack(R.id.fragment_apps, true);
navController.navigate(R.id.fragment_company);
第一行删除返回堆栈,直到它到达我的例子中指定的片段,它是主片段,所以它完全删除了所有返回堆栈,当用户在 fragment_company 中单击返回时,他关闭了应用程序。
您可以像这样覆盖底座 activity 的后压:
override fun onBackPressed() {
val navigationController = nav_host_fragment.findNavController()
if (navigationController.currentDestination?.id == R.id.firstFragment) {
finish()
} else if (navigationController.currentDestination?.id == R.id.secondFragment) {
// do nothing
} else {
super.onBackPressed()
}
}
NavController navController
=Navigation.findNavController(requireActivity(),
R.id.nav_host_fragment);// initialize navcontroller
if (navController.getCurrentDestination().getId() ==
R.id.my_current_frag) //for avoid crash
{
NavDirections action =
DailyInfoSelectorFragmentDirections.actionGoToDestionationFragment();
//for clear current fragment from stack
NavOptions options = new
NavOptions.Builder().setPopUpTo(R.id.my_current_frag, true).build();
navController.navigate(action, options);
}
这是我完成它的方法。
//here the R.id refer to the fragment one wants to pop back once pressed back from the newly navigated fragment
val navOption = NavOptions.Builder().setPopUpTo(R.id.startScorecardFragment, false).build()
//now how to navigate to new fragment
Navigation.findNavController(this, R.id.my_nav_host_fragment)
.navigate(R.id.instoredBestPractice, null, navOption)
我努力了一段时间,以防止后退按钮返回到我的开始片段,在我的情况下,这是一条应该只出现一次的介绍消息。
简单的解决方案是创建一个 global action 指向用户应该停留的目的地。您必须正确设置 app:popUpTo="..."
- 将其设置为您想要弹出的目的地。就我而言,这是我的介绍信息。同时设置 app:popUpToInclusive="true"
您可以像这样简单地做:
getFragmentManager().popBackStack();
如果你想查看计数,你可以这样做:
getFragmentManager().getBackStackEntryCount()
使用此代码
navController.navigateUp();
然后调用新的片段
android 版本 4.1.2
要在这里添加另一个答案,因为上面的 none 对我有用...我们有多个导航图。
findNavController().navigate(R.id.dashboard_graph,null,NavOptions.Builder().setPopUpTo(findNavController().graph.startDestination, true).build())
这是我能够成功清除全部返回堆栈的唯一方法。 Google 真的需要简化一下。
为了
// Navigation library
def nav_version = "2.3.5"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
这个解决方案对我有用
findNavController().popBackStack(R.id.<Current Fragment Id In NavGraph>, true)
findNavController().navigate(R.id.< Your Destination Fragment in NavGraph>)
在我的例子中,我将 Navigation 组件 与 NavigationView(菜单抽屉)一起使用:
1.
mNavController.popBackStack(R.id.ID_OF_FRAGMENT_ROOT_TO_POP, true)
mNavController.navigate(
R.id.DESTINATION_ID,
null,
NavOptions.Builder()
.setPopUpTo(R.id.POP_TO_DESTINATION_ID, true)
.build()
)
我想在点击侧面菜单抽屉上的注销后清除堆栈!
希望对某人有所帮助!
以上解决方案都不适合我。
花了几个小时后,这是我的解决方案:
注意:我有多个 nav_graphs
并且在不同 nav_graphs
的片段之间切换。
- 在 xml 中定义您的操作:
<action
android:id="@id/your_action_id"
app:destination="@id/the_fragment_id_you_want_to_navigate_to"
app:popUpTo="@id/nav_graph_which_contains_destination_fragment"
app:popUpToInclusive="true" />
- 使用上述 Java/Kotlin 代码中的操作进行导航:
findNavController(R.id.your_nav_name)?.apply {
navigate(R.id.your_action_id)
backQueue.clear()
}
我正在使用 android 中的新 Navigation Architecture Component,但在移动到新片段后我无法清除导航堆栈。
示例: 我在 loginFragment 中,我希望在导航到主页片段时从堆栈中清除该片段,以便用户在按下后退按钮时不会返回到 loginFragment。
我正在使用简单的 NavHostFragment.findNavController(Fragment).navigate(R.id.homeFragment) 进行导航。
当前代码:
mAuth.signInWithCredential(credential)
.addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment);
} else {
Log.w(TAG, "signInWithCredential:failure", task.getException());
}
}
});
我尝试使用 NavOptions in the navigate(),但后退按钮仍将我送回 loginFragment
NavOptions.Builder navBuilder = new NavOptions.Builder();
NavOptions navOptions = navBuilder.setPopUpTo(R.id.homeFragment, false).build();
NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment, null, navOptions);
感谢
我必须将 .setClearTask(true) 指定为 NavOption。
mAuth.signInWithCredential(credential)
.addOnCompleteListener(getActivity(), new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Log.d(TAG, "signInWithCredential:success");
NavOptions.Builder navBuilder = new NavOptions.Builder();
NavOptions navOptions = navBuilder.setClearTask(true).build();
NavHostFragment.findNavController(LoginFragment.this).navigate(R.id.homeFragment,null,navOptions);
} else {
Log.w(TAG, "signInWithCredential:failure", task.getException());
}
}
});
注意:清除任务已弃用,官方描述为
This method is deprecated. Use setPopUpTo(int, boolean) with the id of the NavController's graph and set inclusive to true.
旧答案
如果您不想在代码中经历所有这些模糊,您可以简单地检查操作属性中 Launch Options
中的 Clear Task
。
编辑: 自 Android Studio 3.2 Beta 5 起,启动选项中不再显示清除任务 window,但您仍然可以使用它在导航的 XML 代码中,在 action 标签中,通过添加
app:clearTask="true"
首先,将属性 app:popUpTo='your_nav_graph_id'
和 app:popUpToInclusive="true"
添加到操作标签。
<fragment
android:id="@+id/signInFragment"
android:name="com.glee.incog2.android.fragment.SignInFragment"
android:label="fragment_sign_in"
tools:layout="@layout/fragment_sign_in" >
<action
android:id="@+id/action_signInFragment_to_usersFragment"
app:destination="@id/usersFragment"
app:launchSingleTop="true"
app:popUpTo="@+id/main_nav_graph"
app:popUpToInclusive="true" />
</fragment>
其次,导航到目的地,使用上述操作作为参数。
findNavController(fragment).navigate(
SignInFragmentDirections.actionSignInFragmentToUserNameFragment())
有关详细信息,请参阅 docs。
注意:如果您使用方法 navigate(@IdRes int resId)
进行导航,您将无法获得所需的结果。因此,我使用了方法 navigate(@NonNull NavDirections directions)
.
我认为您的问题具体涉及如何使用 Pop Behavior / Pop To / app:popUpTo(在 xml 中)
在文档中,
导航前弹出给定目的地。这将从返回堆栈中弹出所有 non-matching 个目的地,直到找到该目的地。
示例(简单的求职应用程序)
我的 start_screen_nav 图表是这样的:
startScreenFragment (start) -> loginFragment -> EmployerMainFragment
-> loginFragment -> JobSeekerMainFragment
如果我想导航到 EmployerMainFragment
并弹出所有 包括 startScreenFragment
那么代码将是:
<action
android:id="@+id/action_loginFragment_to_employerMainFragment"
app:destination="@id/employerMainFragment"
app:popUpTo="@+id/startScreenFragment"
app:popUpToInclusive="true" />
如果我想导航到 EmployerMainFragment
并弹出所有 排除 startScreenFragment
那么代码将是:
<action
android:id="@+id/action_loginFragment_to_employerMainFragment"
app:destination="@id/employerMainFragment"
app:popUpTo="@+id/startScreenFragment"/>
如果我想导航到 EmployerMainFragment
并弹出 loginFragment
但 不是 startScreenFragment
那么代码将是:
<action
android:id="@+id/action_loginFragment_to_employerMainFragment"
app:destination="@id/employerMainFragment"
app:popUpTo="@+id/loginFragment"
app:popUpToInclusive="true"/>
或
<action
android:id="@+id/action_loginFragment_to_employerMainFragment"
app:destination="@id/employerMainFragment"
app:popUpTo="@+id/startScreenFragment"/>
在我的例子中,我需要在打开新片段之前删除后台堆栈中的所有内容,所以我使用了这段代码
navController.popBackStack(R.id.fragment_apps, true);
navController.navigate(R.id.fragment_company);
第一行删除返回堆栈,直到它到达我的例子中指定的片段,它是主片段,所以它完全删除了所有返回堆栈,当用户在 fragment_company 中单击返回时,他关闭了应用程序。
您可以像这样覆盖底座 activity 的后压:
override fun onBackPressed() {
val navigationController = nav_host_fragment.findNavController()
if (navigationController.currentDestination?.id == R.id.firstFragment) {
finish()
} else if (navigationController.currentDestination?.id == R.id.secondFragment) {
// do nothing
} else {
super.onBackPressed()
}
}
NavController navController
=Navigation.findNavController(requireActivity(),
R.id.nav_host_fragment);// initialize navcontroller
if (navController.getCurrentDestination().getId() ==
R.id.my_current_frag) //for avoid crash
{
NavDirections action =
DailyInfoSelectorFragmentDirections.actionGoToDestionationFragment();
//for clear current fragment from stack
NavOptions options = new
NavOptions.Builder().setPopUpTo(R.id.my_current_frag, true).build();
navController.navigate(action, options);
}
这是我完成它的方法。
//here the R.id refer to the fragment one wants to pop back once pressed back from the newly navigated fragment
val navOption = NavOptions.Builder().setPopUpTo(R.id.startScorecardFragment, false).build()
//now how to navigate to new fragment
Navigation.findNavController(this, R.id.my_nav_host_fragment)
.navigate(R.id.instoredBestPractice, null, navOption)
我努力了一段时间,以防止后退按钮返回到我的开始片段,在我的情况下,这是一条应该只出现一次的介绍消息。
简单的解决方案是创建一个 global action 指向用户应该停留的目的地。您必须正确设置 app:popUpTo="..."
- 将其设置为您想要弹出的目的地。就我而言,这是我的介绍信息。同时设置 app:popUpToInclusive="true"
您可以像这样简单地做:
getFragmentManager().popBackStack();
如果你想查看计数,你可以这样做:
getFragmentManager().getBackStackEntryCount()
使用此代码
navController.navigateUp();
然后调用新的片段 android 版本 4.1.2
要在这里添加另一个答案,因为上面的 none 对我有用...我们有多个导航图。
findNavController().navigate(R.id.dashboard_graph,null,NavOptions.Builder().setPopUpTo(findNavController().graph.startDestination, true).build())
这是我能够成功清除全部返回堆栈的唯一方法。 Google 真的需要简化一下。
为了
// Navigation library
def nav_version = "2.3.5"
implementation "androidx.navigation:navigation-fragment-ktx:$nav_version"
implementation "androidx.navigation:navigation-ui-ktx:$nav_version"
这个解决方案对我有用
findNavController().popBackStack(R.id.<Current Fragment Id In NavGraph>, true)
findNavController().navigate(R.id.< Your Destination Fragment in NavGraph>)
在我的例子中,我将 Navigation 组件 与 NavigationView(菜单抽屉)一起使用:
1.
mNavController.popBackStack(R.id.ID_OF_FRAGMENT_ROOT_TO_POP, true)
mNavController.navigate(
R.id.DESTINATION_ID,
null,
NavOptions.Builder()
.setPopUpTo(R.id.POP_TO_DESTINATION_ID, true)
.build()
)
我想在点击侧面菜单抽屉上的注销后清除堆栈! 希望对某人有所帮助!
以上解决方案都不适合我。 花了几个小时后,这是我的解决方案:
注意:我有多个 nav_graphs
并且在不同 nav_graphs
的片段之间切换。
- 在 xml 中定义您的操作:
<action android:id="@id/your_action_id" app:destination="@id/the_fragment_id_you_want_to_navigate_to" app:popUpTo="@id/nav_graph_which_contains_destination_fragment" app:popUpToInclusive="true" />
- 使用上述 Java/Kotlin 代码中的操作进行导航:
findNavController(R.id.your_nav_name)?.apply { navigate(R.id.your_action_id) backQueue.clear() }