将导航体系结构组件与导航抽屉一起使用

时间:2018-07-10 15:25:13

标签: android android-navigation-drawer android-architecture-components android-architecture-navigation

我正在尝试将Navigation Architecture Component(NavHostFragment)与Navigation Drawer(widget.NavigationView)一起使用。我收到以下两个错误之一。

1)多次从抽屉中选择一个项目时,可能会发生这种情况:

jest.fn()

2)这是从我的真实代码库中发生的,该代码库的设置方式与AFAICT下的简化示例相同。为什么不设置当前导航节点?

isAppPublicRequest

简化代码

MainActivity

java.lang.IllegalArgumentException: navigation destination app.myDomain.navdrawertrials:id/action_rootFragment_to_settingsFragment is unknown to this NavController

main_activity.xml

java.lang.IllegalStateException: no current navigation node

nav_drawer_menu.xml

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.main_activity)

        setupToolbar()
        setupNavDrawer()
        setupNavigation()
    }


    private fun setupToolbar() {
        setSupportActionBar( toolbar )
    }

    private fun setupNavigation() {
        val navController = findNavController( R.id.nav_host_fragment)

        setupActionBarWithNavController( navController, main_activity_drawer_layout )
    }

    private fun setupNavDrawer() {
        val toggle = ActionBarDrawerToggle(
                this,
                main_activity_drawer_layout,
                toolbar,
                R.string.navigation_drawer_open,
                R.string.navigation_drawer_close)

        main_activity_drawer_layout.addDrawerListener(toggle)
        toggle.syncState()


        nav_drawer.setNavigationItemSelectedListener {
            val navController = findNavController( R.id.nav_host_fragment )

            when (it.itemId) {
                R.id.nav_drawer_root_menu_item     -> navController.navigate(R.id.rootFragment)
                R.id.nav_drawer_first_menu_item    -> navController.navigate(R.id.action_rootFragment_to_firstFragment)
                R.id.nav_drawer_settings_menu_item -> navController.navigate(R.id.action_rootFragment_to_settingsFragment)
            }

            main_activity_drawer_layout.closeDrawer(GravityCompat.START)

            true
        }
    }

    override fun onSupportNavigateUp() = findNavController(R.id.nav_host_fragment).navigateUp()
}

main_activity_content.xml

<android.support.v4.widget.DrawerLayout
    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/main_activity_drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <include
        layout="@layout/main_activity_content"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <android.support.design.widget.NavigationView
        android:id="@+id/nav_drawer"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_drawer_header"
        app:menu="@menu/nav_drawer_menu" />

</android.support.v4.widget.DrawerLayout>

nav_graph.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <item
        android:id="@+id/nav_drawer_root_menu_item"
        android:title="To Root" />
    <item
        android:id="@+id/nav_drawer_first_menu_item"
        android:title="To First" />
    <item
        android:id="@+id/nav_drawer_settings_menu_item"
        android:title="To Settings" />
</menu>

root_fragment.xml(其他节点是带有标签的类似空片段)

<android.support.design.widget.CoordinatorLayout
    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:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary" />

    </android.support.design.widget.AppBarLayout>

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:navGraph="@navigation/nav_graph"
        app:defaultNavHost="true"
        />

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="bottom|end"
        android:layout_margin="@dimen/fab_margin"
        app:srcCompat="@android:drawable/ic_dialog_email" />

</android.support.design.widget.CoordinatorLayout>

2 个答案:

答案 0 :(得分:1)

关于第一个错误,根据您的代码,当用户从抽屉中选择“第一个”或“设置”时,他使用action_rootFragment_to_firstFragmentaction_rootFragment_to_settingsFragment动作转移到“第一个”或“设置”片段,但是如果您尝试再次从抽屉中选择“第一”或“设置”,则导航图中的action_rootFragment_to_firstFragmentaction_rootFragment_to_settingsFragment元素内没有firstFragmentsettingsFragment操作。 / p>

解决方案是更改:

when (it.itemId) { 
            R.id.nav_drawer_root_menu_item     -> navController.navigate(R.id.rootFragment) 
            R.id.nav_drawer_first_menu_item    -> navController.navigate(R.id.action_rootFragment_to_firstFragment) 
            R.id.nav_drawer_settings_menu_item -> navController.navigate(R.id.action_rootFragment_to_settingsFragment) 
        } 

收件人:

   when (it.itemId) { 
            R.id.nav_drawer_root_menu_item     -> navController.navigate(R.id.rootFragment) 
            R.id.nav_drawer_first_menu_item    -> navController.navigate(R.id.firstFragment) 
            R.id.nav_drawer_settings_menu_item -> navController.navigate(R.id.settingsFragment) 
        } 

更好的解决方案是将目标绑定到菜单驱动的UI组件(在您的情况下为抽屉),将菜单项ID更改为与目标ID相同,如下所示:

<item
    android:id="@+id/rootFragment"
    android:title="To Root" />
<item
    android:id="@+id/firstFragment"
    android:title="To First" />
<item
    android:id="@+id/settingsFragment"
    android:title="To Settings" />

并添加

 setupWithNavController(nav_view, navController )

在您的主要活动中,而不是

nav_drawer.setNavigationItemSelectedListener {
        val navController = findNavController( R.id.nav_host_fragment )

        when (it.itemId) {
            R.id.nav_drawer_root_menu_item     -> navController.navigate(R.id.rootFragment)
            R.id.nav_drawer_first_menu_item    -> navController.navigate(R.id.action_rootFragment_to_firstFragment)
            R.id.nav_drawer_settings_menu_item -> navController.navigate(R.id.action_rootFragment_to_settingsFragment)
        }

        main_activity_drawer_layout.closeDrawer(GravityCompat.START)

        true
    }

答案 1 :(得分:0)

2)如果在方向改变时发生碰撞。在活动中使用以下内容 将导航版本模块升级到2.2.0或更高版本

implementation "androidx.navigation:navigation-fragment-ktx:2.2.0"
implementation "androidx.navigation:navigation-ui-ktx:2.2.0"