Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/219.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 带有NavigationDrawer的导航组件_Android_Navigation Drawer_Android Navigation_Android Architecture Navigation - Fatal编程技术网

Android 带有NavigationDrawer的导航组件

Android 带有NavigationDrawer的导航组件,android,navigation-drawer,android-navigation,android-architecture-navigation,Android,Navigation Drawer,Android Navigation,Android Architecture Navigation,我正在尝试在项目中使用导航组件实现NavigationDrawer。 我有一个MainActivity作为入口点和多个目的地。我已经将抽屉菜单项链接到nav_graph.xml中的目的地,一切正常 我的NavigationDrawer中有一个“注销”菜单项选项,单击它,我将启动LoginActivity。我的问题是 我将LoginActivity添加到我的导航图中,并将其链接到抽屉中的注销菜单项,这是正确的方法吗 一旦LoginActivity启动,当用户按下system back按钮时,我希望

我正在尝试在项目中使用导航组件实现NavigationDrawer。 我有一个MainActivity作为入口点和多个目的地。我已经将抽屉菜单项链接到nav_graph.xml中的目的地,一切正常

我的NavigationDrawer中有一个“注销”菜单项选项,单击它,我将启动LoginActivity。我的问题是

  • 我将LoginActivity添加到我的导航图中,并将其链接到抽屉中的注销菜单项,这是正确的方法吗
  • 一旦LoginActivity启动,当用户按下system back按钮时,我希望应用程序转到launcher屏幕,而不是堆栈中的上一个目标。这是否可以通过导航组件实现
  • 这是我的nav_graph.xml

    <?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/dashboardFragment">
    
        <fragment
            android:id="@+id/dashboardFragment"
            android:name="com.example.fragment.DashboardFragment"
            android:label="DashboardFragment"
            tools:layout="@layout/fragment_dashboard" />
        <fragment
            android:id="@+id/profileFragment"
            android:name="com.example.fragment.ProfileFragment"
            android:label="ProfileFragment"
            tools:layout="@layout/fragment_profile" />
        <fragment
            android:id="@+id/settingsFragment"
            android:name="com.example.fragment.SettingsFragment"
            android:label="SettingsFragment"
            tools:layout="@layout/fragment_sale_edit" />
        <activity
            android:id="@+id/loginActivity"
            android:name="com.example.activity.LogoutActivity"
            android:label="LogoutActivity"></activity>
    </navigation>
    
    
    
    这是我的drawer_menu.xml

    <?xml version="1.0" encoding="utf-8"?>
    <menu xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        tools:showIn="navigationView">
    
        <group android:checkableBehavior="single">
            <item
                android:id="@+id/dashboardFragment"
                android:icon="@drawable/ic_menu_camera"
                android:title="Dashboard" />
            <item
                android:id="@+id/profileFragment"
                android:icon="@drawable/ic_menu_gallery"
                android:title="Profile" />
            <item
                android:id="@+id/settingsFragment"
                android:icon="@drawable/ic_menu_slideshow"
                android:title="Sale Edits" />
            <item
                android:id="@+id/loginActivity"
                android:icon="@drawable/ic_menu_manage"
                android:title="Logout" />
        </group>
    
    </menu>
    
    
    
    <fragment
            android:id="@+id/navHostFragment"
            android:name="androidx.navigation.fragment.NavHostFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:defaultNavHost="true"
            app:navGraph="@navigation/nav_graph"/>
    

    回答您的问题:

    我将LoginActivity添加到我的导航图中,并将其链接到抽屉中的注销菜单项,这是正确的方法吗

    是的,这是一项新活动的午餐方式,但你想要的与常规活动略有不同

    要实现您想要的功能,您必须使用loginActivity启动应用程序(使其成为您的启动器活动),此活动将检查用户的会话(具有启动屏幕或加载屏幕),如果会话存在,它将为您的主要活动提供午餐,如果没有,则用户必须登录,然后您为主要活动提供午餐

    要使用导航组件实现这一点,您需要为登录活动创建一个新的导航图,并将主活动链接放在那里

    使用此设置,您应该在新任务中使用主活动,然后完成登录活动,这样,返回主活动将关闭应用程序并从登录活动返回


    如果这个答案不清楚,请告诉我,我可以解释更多。

    我认为更好的解决方案是使用登录作为片段,而不是活动,工具栏处理应该从您的活动中完成。 您的活动应该如下所示:

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)
        supportActionBar?.setDisplayHomeAsUpEnabled(true)
        supportActionBar?.setDisplayShowHomeEnabled(true)
        setupActionBarWithNavController(this, findNavController(nav_host_fragment),drawer_layout)
        setupWithNavController(nav_view, findNavController(nav_host_fragment))
    
        NavHostFragment.findNavController( nav_host_fragment ).addOnNavigatedListener { controller, destination ->
            when(destination.id) {
                R.id.loginFragment -> {
                    drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
                    toolbar.visibility= View.GONE
                }
                R.id.dashboardFragment -> {
                    drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
                    toolbar.visibility= View.VISIBLE
                }
                else -> {
                    drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
                    toolbar.visibility= View.VISIBLE
                }
            }
        }
    }
    
    override fun onBackPressed() {
        if (drawer_layout.isDrawerOpen(GravityCompat.START)) {
            drawer_layout.closeDrawer(GravityCompat.START)
        } else {
            super.onBackPressed()
        }
    }
    
    override fun onOptionsItemSelected(item: MenuItem?): Boolean {
        when(item?.itemId) {
            android.R.id.home -> {
                if(NavHostFragment.findNavController( nav_host_fragment ).currentDestination.id==R.id.dashboardFragment) {
                    drawer_layout.openDrawer(GravityCompat.START)
                    return true
                }
            }
        }
        return super.onOptionsItemSelected(item)
    }
    
    override fun onSupportNavigateUp()= findNavController(nav_host_fragment).navigateUp()
    

    我也一直在试图找到解决这个问题的方法,结果非常简单

    !!!从
    nav_graph.xml
    和处理或连接的所有代码实例中删除活动导航项。(例如,我使用AppBarConfiguration,必须从中删除id)

    只需从导航抽屉中使用要处理的菜单项的单击侦听器

    navView = findViewById(R.id.nav_view)
    val logoutItem = navView.menu.findItem(R.id.loginActivity)
    logoutItem.setOnMenuItemClickListener {
        val loginIntent = Intent(this, LoginActivity::class.java)
        startActivity(loginIntent)
        finish()
        return@setOnMenuItemClickListener true
    }
    

    为什么不使用fragment而不是activity进行登录?很抱歉,重新登录太晚了。通过将登录设置为片段,它也会使工具栏出现在登录屏幕上,我不想让工具栏也出现在登录屏幕上,这将增加为每个片段创建工具栏的开销,因为所有片段都是相同的。对于登录屏幕,我有一个完全不同的流程,例如登录->注册或登录->忘记密码等。我不想混淆它们。您可以使用登录作为片段,并从NavHostFragment.findNavController(nav_host_fragment.addOnNavigatedListener()中的主活动处理工具栏逻辑,这是比登录活动更好的解决方案。您的意思是,在这种情况下,当用户单击“注销”选项时,以编程方式隐藏工具栏?登录后再次显示?是的,根据当前目的地处理工具栏逻辑,我在这里添加了一些代码:我认为添加启动屏幕不是Android应用程序的现代方式。此外,根据我在这里读到的@android_user导航原则,不建议将登录屏幕作为起始目的地。这在很大程度上取决于您的应用程序,启动屏幕是在您检查用户会话时提供到应用程序的过渡,但如果这是即时的,并且不需要任何时间,则您不需要启动。NavComponent仍在开发中,就其当前状态而言,在活动和NestedGraph之间导航并不符合行业惯例(至少我无法满足所有需求),因此您可以实现自定义导航器以满足您的需求,或者采纳我的建议,直到找到更好的方法为止。如果您找到任何其他解决方案,请告诉我我的应用程序设计不需要启动屏幕。我没有太多的数据加载到我的应用程序启动和我的NavComponent没有启动屏幕工作得很好。所以,现在我并没有改变任何东西,除了当用户点击登录屏幕上的系统返回时,我只是使用意图返回到启动器屏幕,这样我就能够实现我所能做到的。将来可能会有更好的解决方案。我知道这可能是一种方式,但我最终在这里编写了太多代码(不需要),并且将来很难将不同的导航图合并到一个导航图中。现在,我只是将登录和主屏幕的导航图分开,当用户单击登录屏幕上的后退按钮时,我使用意图返回到启动器。