Android 带有NavigationDrawer的导航组件
我正在尝试在项目中使用导航组件实现NavigationDrawer。 我有一个MainActivity作为入口点和多个目的地。我已经将抽屉菜单项链接到nav_graph.xml中的目的地,一切正常 我的NavigationDrawer中有一个“注销”菜单项选项,单击它,我将启动LoginActivity。我的问题是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按钮时,我希望
<?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没有启动屏幕工作得很好。所以,现在我并没有改变任何东西,除了当用户点击登录屏幕上的系统返回时,我只是使用意图返回到启动器屏幕,这样我就能够实现我所能做到的。将来可能会有更好的解决方案。我知道这可能是一种方式,但我最终在这里编写了太多代码(不需要),并且将来很难将不同的导航图合并到一个导航图中。现在,我只是将登录和主屏幕的导航图分开,当用户单击登录屏幕上的后退按钮时,我使用意图返回到启动器。