Android 导航:从同一片段访问 NavHostFragment
Android Navigation: Access NavHostFragment from same Fragment
目前我有以下场景:用户必须登录才能使用该应用程序。这意味着我使用了 2 nav_graphs,一个用于所有内容的主图,然后是一个嵌套的主页图,用于在您登录后查看视图。
登录后,应该会出现一个底部导航栏,用于更改主页图中的选项卡。
我有以下 home_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<fragment
android:id="@+id/home_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/home_graph"
app:defaultNavHost="true"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
app:menu="@menu/navigation_items"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
而且我希望能够在底部导航视图中更改选项卡,所以我使用 bottomNavigationView.setOnNavigationItemSelectedListener
在 HomeFragement.kt 中设置了这个逻辑。
不幸的是,当我尝试在 home_fragment.xml 中获取 home_nav_host_fragment
时,我无法获取,因为片段中的 homeNavController = findNavController()
只能找到 main_nav_host_fragment
主要是 activity.
我希望 findNavController()
改为 return home_nav_host_fragment
,但是因为此方法仅搜索父 NavController 而不是同一级别的 NavController,所以找不到我想要的。
有没有更好的结构可以解决这个问题?谢谢
最好将 popUpTo
与 popUpToInclusive
结合使用来创建 单向导航操作 - 为了使用单个图形,而不是两个断开连接的图形。这只应应用于图中的前 1-2 个片段,例如。后退按钮无法导航回初始屏幕或登录屏幕,因为这些操作不计入 "the expected behavior".
<fragment
android:id="@+id/splashFragment"
android:name="com.acme.fragment.SplashFragment"
tools:layout="@layout/fragment_splash"
android:label="fragment_splash">
<action
android:id="@+id/action_splashFragment_to_loginFragment"
app:destination="@id/loginFragment"
app:popUpTo="@id/splashFragment"
app:popUpToInclusive="true"/>
</fragment>
这不是正确的方法。相反,当您在登录图上时,您应该 listen for navigation events 并隐藏 BottomNavigationView
:
navController.addOnDestinationChangedListener { _, destination, _ ->
if(destination.parent!!.id == R.id.login_graph) {
toolbar.visibility = View.GONE
bottomNavigationView.visibility = View.GONE
} else {
toolbar.visibility = View.VISIBLE
bottomNavigationView.visibility = View.VISIBLE
}
}
然后,您可以在 best practices for user login.
之后仅使用一个图表
目前我有以下场景:用户必须登录才能使用该应用程序。这意味着我使用了 2 nav_graphs,一个用于所有内容的主图,然后是一个嵌套的主页图,用于在您登录后查看视图。
登录后,应该会出现一个底部导航栏,用于更改主页图中的选项卡。
我有以下 home_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.home.HomeFragment">
<fragment
android:id="@+id/home_nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
app:navGraph="@navigation/home_graph"
app:defaultNavHost="true"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_navigation"
app:menu="@menu/navigation_items"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
而且我希望能够在底部导航视图中更改选项卡,所以我使用 bottomNavigationView.setOnNavigationItemSelectedListener
在 HomeFragement.kt 中设置了这个逻辑。
不幸的是,当我尝试在 home_fragment.xml 中获取 home_nav_host_fragment
时,我无法获取,因为片段中的 homeNavController = findNavController()
只能找到 main_nav_host_fragment
主要是 activity.
我希望 findNavController()
改为 return home_nav_host_fragment
,但是因为此方法仅搜索父 NavController 而不是同一级别的 NavController,所以找不到我想要的。
有没有更好的结构可以解决这个问题?谢谢
最好将 popUpTo
与 popUpToInclusive
结合使用来创建 单向导航操作 - 为了使用单个图形,而不是两个断开连接的图形。这只应应用于图中的前 1-2 个片段,例如。后退按钮无法导航回初始屏幕或登录屏幕,因为这些操作不计入 "the expected behavior".
<fragment
android:id="@+id/splashFragment"
android:name="com.acme.fragment.SplashFragment"
tools:layout="@layout/fragment_splash"
android:label="fragment_splash">
<action
android:id="@+id/action_splashFragment_to_loginFragment"
app:destination="@id/loginFragment"
app:popUpTo="@id/splashFragment"
app:popUpToInclusive="true"/>
</fragment>
这不是正确的方法。相反,当您在登录图上时,您应该 listen for navigation events 并隐藏 BottomNavigationView
:
navController.addOnDestinationChangedListener { _, destination, _ ->
if(destination.parent!!.id == R.id.login_graph) {
toolbar.visibility = View.GONE
bottomNavigationView.visibility = View.GONE
} else {
toolbar.visibility = View.VISIBLE
bottomNavigationView.visibility = View.VISIBLE
}
}
然后,您可以在 best practices for user login.
之后仅使用一个图表