【问题标题】:Navigation Component with NavigationDrawer带有 NavigationDrawer 的导航组件
【发布时间】:2018-07-19 05:21:00
【问题描述】:

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

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

  1. 我将 LoginActivity 添加到我的 nav_graph 并将其链接到抽屉中的注销菜单项,这是正确的方法吗?
  2. 一旦 LoginActivity 启动,当用户按下系统后退按钮时,我希望应用程序转到启动器屏幕而不是堆栈中的先前目标。这可以通过导航组件实现吗?

这是我的 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"/>

【问题讨论】:

  • 为什么不使用片段而不是活动登录?
  • 抱歉回复晚了。通过将登录作为片段,它也使工具栏出现在登录屏幕上,我不希望在登录屏幕中也有工具栏,这将是为每个片段创建工具栏的开销,当它对所有片段都相同时。我有一个完全不同的登录屏幕流程,例如登录->注册或登录->忘记密码等。我不想混淆它们
  • 您可以使用登录作为片段并处理 NavHostFragment.findNavController( nav_host_fragment ).addOnNavigatedListener() 中主要活动的工具栏逻辑,这是比登录活动更好的解决方案。
  • 您的意思是,在这种情况下,当用户单击注销选项时,以编程方式隐藏工具栏?并在登录后再次显示?
  • 是的,根据当前目的地处理工具栏逻辑,我在这里添加了一些代码:stackoverflow.com/a/51491743/1268507

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


【解决方案1】:

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

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()

【讨论】:

  • 我知道这可能是一种方式,但我最终在这里编写了太多代码(不需要),并且将来很难将不同的导航图合并为一个。现在,我只是将登录和主屏幕的导航图分开,当用户单击登录屏幕上的后退按钮时,我正在使用 Intent 返回启动器。
【解决方案2】:

回答您的问题:

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

是的,这就是你应该如何安排新活动的方式,但你想要的与常规活动有点不同。

要实现你想要的,你必须使用 loginActivity 启动你的应用程序(让它成为你的启动器活动),这个活动将检查用户的会话(有一个启动屏幕或加载屏幕),如果一个会话存在,它将午餐您的主要活动,如果不是用户必须登录,然后您午餐主要活动。

要使用导航组件执行此操作,您需要为登录活动创建一个新的导航图,并在其中放置您的主要活动链接。

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

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

【讨论】:

  • 我认为添加启动画面并不是现代的安卓应用方式。另外,不建议根据我在此处阅读的导航原则将登录屏幕作为起始目的地developer.android.com/topic/libraries/architecture/navigation/…
  • @android_user 这在很大程度上取决于您的应用程序,启动屏幕是在您检查用户会话时提供到应用程序的过渡,但如果这是即时的并且不需要任何时间,那么您不要不需要飞溅。 NavComponent 仍在开发中,作为其当前状态,在活动和嵌套图之间导航不符合行业惯例(至少我无法满足我的所有需求),因此您可以实现自定义导航器以满足您的需求或采用我的建议,直到有更好的方法。如果您找到任何其他解决方案,请告诉我
  • 我的应用程序设计不需要启动画面。我的应用程序启动时没有太多数据要加载,而且没有启动画面的 NavCompoment 运行良好。因此,现在我没有改变任何东西,除了当用户在登录屏幕上点击系统时,我只是使用 Intent 返回启动器屏幕,这样我就可以实现我能做到的。将来可能会有更好的解决方案。
【解决方案3】:

我也一直在尝试解决这个问题,结果很简单。

!!!从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
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多