【问题标题】:How to navigate back in nested graph from the third level to the second level?如何在嵌套图中从第三级导航回第二级?
【发布时间】:2020-08-14 13:10:49
【问题描述】:

我有一个带有Navigation DrawerSingle Activity 项目。我通过Navigation Components实现了导航的可能性。我创建了一个nav_graph.xml,它可以从Navigation Drawer 路由和打开每个Fragment。对于一级路由就足够了。但我的项目有两级,有时是三级路由。所以我为 nav_nested_settings 创建了一个嵌套导航图。

<?xml version="1.0" encoding="utf-8"?>
<navigation 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"
    android:id="@+id/nav_graph"
    app:startDestination="@id/nav_fragment_home">

    <fragment
        android:id="@+id/nav_fragment_home"
        android:name="com.app.ui.fragment.home.HomeFragment"
        android:label="@string/nav_home"
        tools:layout="@layout/fragment_home">
        // other actions ...
        <action
            android:id="@+id/action_nav_fragment_home_to_nav_fragment_fragment"
            app:destination="@id/nav_nested_settings" />
    </fragment>
    // ... other fragments
    <fragment
        android:id="@+id/nav_fragment_search"
        android:name="com.app.ui.fragment.search.SearchFragment"
        android:label="@string/nav_search"
        tools:layout="@layout/fragment_search" />
    <include app:graph="@navigation/nav_settings" />
</navigation>

嵌套图是:

<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tool="http://schemas.android.com/tools"
    android:id="@+id/nav_nested_settings"
    android:label="@string/nav_settings"
    app:startDestination="@id/nav_fragment_settings">
    <fragment
        android:id="@+id/nav_fragment_settings"
        android:name="com.app.ui.fragment.settings.main.SettingsFragment"
        android:label="@string/nav_settings"
        tool:layout="@layout/fragment_settings">
        <action
            android:id="@+id/action_nav_fragment_settings_to_nav_fragment_settings_ads"
            app:destination="@id/nav_fragment_settings_ads" />
        <action
            android:id="@+id/action_nav_fragment_settings_to_nav_fragment_settings_app"
            app:destination="@id/nav_fragment_settings_app" />
        <action
            android:id="@+id/action_nav_fragment_settings_to_nav_fragment_settings_home"
            app:destination="@id/nav_fragment_settings_home" />
    </fragment>
    <fragment
        android:id="@+id/nav_fragment_settings_ads"
        android:name="com.app.ui.fragment.settings.ads.SettingsAdsFragment"
        android:label="@string/nav_settings_ads"
        tool:layout="@layout/fragment_settings_ads" />
    <fragment
        android:id="@+id/nav_fragment_settings_app"
        android:name="com.app.ui.fragment.settings.app.SettingsAppFragment"
        android:label="@string/nav_settings_app"
        tool:layout="@layout/fragment_settings_app" />
    <fragment
        android:id="@+id/nav_fragment_settings_home"
        android:name="com.app.ui.fragment.settings.home.SettingsHomeFragment"
        android:label="@string/nav_settings_home"
        tool:layout="@layout/fragment_settings_home">
    </fragment>
</navigation>

如果我从Navigation Drawer 中选择Settings,应用程序会打开它。然后我点击ads / app / home 按钮并打开下一个Fragment。但是,如果我点击应用工具栏中的back 按钮或箭头 - 什么都不会发生。

如何解决这个问题?如何在嵌套图中从第三级导航回第二级?

更新 01 // 添加了设置 NavController 和 AppBarConfiguration 的函数

private fun initNavigation() {
        mNavController = findNavController(R.id.navHostFragment)
        navView.setupWithNavController(mNavController)
        mAppBarConfiguration = AppBarConfiguration(mNavController.graph, drawerLayout)
        setupActionBarWithNavController(mNavController, mAppBarConfiguration)
}

更新02 我发现了一件有用的事情/错误。后退按钮工作正常,无需任何额外代码。但是,当我单击后退按钮时,应用程序会重复前面的操作“例如,从 SettingsFragment 转到 SettingsAdsFragment”。 我使用带有默认策略的 moxy lib - AddToEndSingleStrategy

【问题讨论】:

  • 检查您的Single Activity 是否覆盖了onSupportNavigateUp(),这是我从您分享的内容中唯一想到的。 override fun onSupportNavigateUp(): Boolean = navController.navigateUp()
  • @DatPhamTat,是的。 override fun onSupportNavigateUp(): Boolean { return mNavController.navigateUp(mAppBarConfiguration) || super.onSupportNavigateUp() } 我可以从 Navigation Drawer Fragments(一级)返回
  • 您的问题似乎出在您的 upd02 评论中,但您没有包含任何代码。
  • @ianhanniballake 因为我认为它不会破坏应用程序流程。通常,它工作正常。

标签: android android-fragments navigation android-architecture-navigation


【解决方案1】:

根据您的评论,我认为您的 onSupportNavigateUp() 并不完全正确。我已经用navDrawer和导航实现了几个应用程序,我覆盖onSupportNavigateUp()的方式如下:

// the activity hosting your navigation
class HostActivity : AppCompatActivity {
    // flag if for the currently shown fragment, navigating up is enabled
    // should be false for top level fragments, i.e. those accessible from navDrawer
    // should be set to true for lower level fragments
    private var canNavigateUp: Boolean = false
    
    ...

    override fun onSupportNavigateUp(): Boolean {
        return if (canNavigateUp) {
            mNavController.navigateUp()
        } else {
            NavigationUI.navigateUp(mNavController, mAppBarConfiguration)
        }
    }

    fun setNavigation(navigateUpEnabled: Boolean) {
        supportActionBar?.let { actionBar ->
            canNavigateUp = navigateUpEnabled
            if (navigateUpEnabled) {
                // set up icon
                actionBar.setHomeAsUpIndicator(null)
                lockUnlockDrawer(lock = true)
            } else {
                // set drawer icon
                actionBar.setDisplayShowHomeEnabled(true)
                lockUnlockDrawer(lock = false)
            }
        }
    }
}

然后,对于顶级片段,即可以直接从 navDrawer 访问的片段:

class TopLevelFragment : Fragment() {
    ...
    
    override fun onResume() {
        super.onResume()
        (activity as? HostActivity)?.setNavigation(false)
    }
}

对于较低级别的片段(ads/app/home):

class LowLevelFragment : Fragment() {
    ...
    
    override fun onResume() {
        super.onResume()
        (activity as? HostActivity)?.setNavigation(true)
    }
}

假设您正确设置了mNavControllermAppBarConfiguration,这应该可以工作。

【讨论】:

  • 我已从您的答案中复制了所有代码,但这对我没有帮助。您提到我应该正确设置我的 NavController 和 AppBarConfiguration。我刚刚更新了我的问题并添加了一个设置它们的功能。你能检查一下吗?
  • 我制作了一个反映您的案例的工作演示,您可以在此处找到它:github.com/phamtdat/NavigationDemo 检查并尝试将其与您的代码进行比较。
  • 谢谢!我刚刚检查过,我的代码是一样的。而且我认为问题的根源隐藏在 Moxy lib 策略中
  • 当您使用setupActionBarWithNavController() 时,您不应该与setDisplayShowHomeEnabled 混淆 - 根据您在AppBarConfiguration 上设置的顶级目的地,它已经为您做正确的事情。
【解决方案2】:

我找到了解决办法!

我应该对 Moxy 库使用正确的策略。是的,我没有在主题中提及该库,因为我认为它不会破坏应用程序流程。

接口方法的旧策略类型

StateStrategyType(AddToEndSingleStrategy::class)
interface SettingsView : BaseMvpView {
    fun showManageAdsFragment()
    fun showManageAppUIFragment()
    fun showManageHomeUIFragment()
}

接口方法的新策略类型

StateStrategyType(SkipStrategy::class)
interface SettingsView : BaseMvpView {
    fun showManageAdsFragment()
    fun showManageAppUIFragment()
    fun showManageHomeUIFragment()
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-29
    • 2014-06-26
    • 2023-01-07
    • 2011-04-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-02
    相关资源
    最近更新 更多