如何使用 Android 导航抽屉从另一个片段打开一个片段?
How to open a fragment from another fragment using the Android Navigation Drawer?
我有一个带有菜单的 Android 导航抽屉,点击项目打开片段。目前很好。
其中一些片段需要打开一个新片段以获取更多详细信息。我使用第一个片段中的这段代码来做到这一点:
getParentFragmentManager().beginTransaction().replace(R.id.nav_host_fragment_content_main, new MySecondFragment(), null).commit();
点击后退按钮(左上角的后退箭头)不会将我带回 MyFirstFragment。它通过一个例外:
java.lang.IllegalStateException: Fragment MyFirstFragment not
associated with a fragment manager.
我可以使用其他代码:
getParentFragmentManager().beginTransaction().add(R.id.nav_host_fragment_content_main, new MySecondFragment(), null).commit();
但是使用这段代码,两个片段同时可见。我的意思是,显示了 MySecondFragment 视图,但我在后台看到了 MyFirstFragment 视图。
关于如何从 MyFirstFragment 打开 MySecondFragment 的任何想法,然后,如果按下后退箭头,我想 return 到 MyFirstFragment 之前所在的相同位置。
谢谢
But with this code both fragments are visible at the same time.
您可以将背景颜色设置为其根部layout.xml
您也可以使用fragmentTransaction.addToBackStack(null)
将此事务添加到后台堆栈
新答案:
使用导航抽屉,片段事务似乎发生在 NavHostFragment 及其 FragmentTransactionManager 下。
这迫使我们获取它的 childFragmentManager()
并将其用于检查 backStackEntryCount
.
因此,仅将嵌套片段添加到父后退堆栈是不够的。我们需要覆盖 onBackPressed
和 onSupportNavigateUp
并在返回和弹出它时考虑 NavHostFragment
的后栈。
private fun handleNestedFragmentsBackStack(): Boolean {
val navHostChildFragmentManager = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment_content_main)?.childFragmentManager
return if (navHostChildFragmentManager?.backStackEntryCount!! > 1) {
navHostChildFragmentManager.popBackStack()
false
} else {
val navController = findNavController(R.id.nav_host_fragment_content_main)
navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
override fun onBackPressed() {
handleNestedFragmentsBackStack()
}
override fun onSupportNavigateUp(): Boolean {
return handleNestedFragmentsBackStack()
}
现在,将第二个片段添加到父级的后台堆栈时,请记住父级不是 Activity,而是 NavHostFragment。
您可以按照初始答案中的建议进行片段交易。
初始答案:
应该适用于标准片段交易
将您的片段添加到后台堆栈应该可以解决您的问题
FragmentTransaction ft = getParentFragmentManager().beginTransaction()
ft.replace(R.id.nav_host_fragment_content_main, new MySecondFragment(), null)
ft.addToBackStack(MySecondFragment.class.getName()) // you can use a string here, using the class name is just convenient
ft.commit();
按下后退按钮时,您将浏览后退堆栈。
Kotlin 代码中相同:
parentFragmentManager.commit {
replace(R.id.nav_host_fragment_content_main, MySecondFragment())
addToBackStack(MySecondFragment::class.java.name)
}
解决方案在Java代码中:
在带有导航抽屉的 AppCompatActivity 中:
@Override
public boolean onSupportNavigateUp() {
FragmentManager oChildFragmentManager = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment_content_main).getChildFragmentManager();
if(oChildFragmentManager.getBackStackEntryCount() > 1){
oChildFragmentManager.popBackStack();
return true;
}
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp();
}
@Override
public void onBackPressed() {
FragmentManager oChildFragmentManager = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment_content_main).getChildFragmentManager();
if(oChildFragmentManager.getBackStackEntryCount() > 1){
oChildFragmentManager.popBackStack();
return;
}
super.onBackPressed();
}
任何时候打开片段都不要忘记addToBackStack:
getParentFragmentManager().beginTransaction().replace(R.id.nav_host_fragment_content_main, new MyNewFragment()).addToBackStack("").commit();
我有一个带有菜单的 Android 导航抽屉,点击项目打开片段。目前很好。 其中一些片段需要打开一个新片段以获取更多详细信息。我使用第一个片段中的这段代码来做到这一点:
getParentFragmentManager().beginTransaction().replace(R.id.nav_host_fragment_content_main, new MySecondFragment(), null).commit();
点击后退按钮(左上角的后退箭头)不会将我带回 MyFirstFragment。它通过一个例外:
java.lang.IllegalStateException: Fragment MyFirstFragment not associated with a fragment manager.
我可以使用其他代码:
getParentFragmentManager().beginTransaction().add(R.id.nav_host_fragment_content_main, new MySecondFragment(), null).commit();
但是使用这段代码,两个片段同时可见。我的意思是,显示了 MySecondFragment 视图,但我在后台看到了 MyFirstFragment 视图。
关于如何从 MyFirstFragment 打开 MySecondFragment 的任何想法,然后,如果按下后退箭头,我想 return 到 MyFirstFragment 之前所在的相同位置。
谢谢
But with this code both fragments are visible at the same time.
您可以将背景颜色设置为其根部layout.xml
您也可以使用fragmentTransaction.addToBackStack(null)
将此事务添加到后台堆栈
新答案:
使用导航抽屉,片段事务似乎发生在 NavHostFragment 及其 FragmentTransactionManager 下。
这迫使我们获取它的 childFragmentManager()
并将其用于检查 backStackEntryCount
.
因此,仅将嵌套片段添加到父后退堆栈是不够的。我们需要覆盖 onBackPressed
和 onSupportNavigateUp
并在返回和弹出它时考虑 NavHostFragment
的后栈。
private fun handleNestedFragmentsBackStack(): Boolean {
val navHostChildFragmentManager = supportFragmentManager
.findFragmentById(R.id.nav_host_fragment_content_main)?.childFragmentManager
return if (navHostChildFragmentManager?.backStackEntryCount!! > 1) {
navHostChildFragmentManager.popBackStack()
false
} else {
val navController = findNavController(R.id.nav_host_fragment_content_main)
navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
}
}
override fun onBackPressed() {
handleNestedFragmentsBackStack()
}
override fun onSupportNavigateUp(): Boolean {
return handleNestedFragmentsBackStack()
}
现在,将第二个片段添加到父级的后台堆栈时,请记住父级不是 Activity,而是 NavHostFragment。 您可以按照初始答案中的建议进行片段交易。
初始答案:
应该适用于标准片段交易
将您的片段添加到后台堆栈应该可以解决您的问题
FragmentTransaction ft = getParentFragmentManager().beginTransaction()
ft.replace(R.id.nav_host_fragment_content_main, new MySecondFragment(), null)
ft.addToBackStack(MySecondFragment.class.getName()) // you can use a string here, using the class name is just convenient
ft.commit();
按下后退按钮时,您将浏览后退堆栈。
Kotlin 代码中相同:
parentFragmentManager.commit {
replace(R.id.nav_host_fragment_content_main, MySecondFragment())
addToBackStack(MySecondFragment::class.java.name)
}
在带有导航抽屉的 AppCompatActivity 中:
@Override
public boolean onSupportNavigateUp() {
FragmentManager oChildFragmentManager = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment_content_main).getChildFragmentManager();
if(oChildFragmentManager.getBackStackEntryCount() > 1){
oChildFragmentManager.popBackStack();
return true;
}
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment_content_main);
return NavigationUI.navigateUp(navController, mAppBarConfiguration) || super.onSupportNavigateUp();
}
@Override
public void onBackPressed() {
FragmentManager oChildFragmentManager = getSupportFragmentManager().findFragmentById(R.id.nav_host_fragment_content_main).getChildFragmentManager();
if(oChildFragmentManager.getBackStackEntryCount() > 1){
oChildFragmentManager.popBackStack();
return;
}
super.onBackPressed();
}
任何时候打开片段都不要忘记addToBackStack:
getParentFragmentManager().beginTransaction().replace(R.id.nav_host_fragment_content_main, new MyNewFragment()).addToBackStack("").commit();