如何在 Android 中使用 Navigation Drawer 设置导航组件? [英] How to set up Navigation Component with Navigation Drawer in Android?

查看:38
本文介绍了如何在 Android 中使用 Navigation Drawer 设置导航组件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何设置带有导航抽屉的导航组件?如何在我的应用中使用它?

How do I set up navigation component with navigation drawer? How do I use it in my app?

可以用一个 Activity 完成所有事情吗?

Can everything be done with one Activity?

如何仅使用一个具有动态工具栏可见性的 Activity 和片段来处理工具栏可见性.此外,我需要关闭抽屉并使其无法访问.

How do I handle toolbar visibility with just one Activity and fragments which have a dynamic toolbar visibility. Also, there are fragments which I need to close the drawer and make it inaccessible.

这个问题是一个自我回答的问题,更像是一个教程,而不是现实生活中的 QA.

推荐答案

如何设置带有导航抽屉的导航组件?

How do I set up navigation component with navigation drawer?

如何在我的应用中使用它?

How do I use it in my app?

导航抽屉的设置与导航组件略有不同.

The navigation drawer set up differs a little when it comes to Navigation component.

注意,如果您创建一个带有抽屉导航的新应用,则不需要当前教程.但是,如果您决定在应用程序的后期添加抽屉,我将解释一些可能看起来很奇怪的事情

首先,您需要设置 activity_main.xmlMainActivity 为导航架构做好准备:

First, you need to set up your activity_main.xml and MainActivity to be ready for the Navigation Architecture:

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.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/drawer_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    tools:openDrawer="start">

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

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:fitsSystemWindows="true"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer" />

</androidx.drawerlayout.widget.DrawerLayout>

其中 app_bar_main 只是:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay">

        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:popupTheme="@style/AppTheme.PopupOverlay" />

    </com.google.android.material.appbar.AppBarLayout>

    <include layout="@layout/content_main" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

content_main 是你的片段将被保存的地方:

And the content_main is where your fragments are going to be held:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:showIn="@layout/app_bar_main">

    <fragment
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:defaultNavHost="true"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:navGraph="@navigation/mobile_navigation" />
</androidx.constraintlayout.widget.ConstraintLayout>

您应该知道的事情:活动不得在 AndroidManifest.xml 上设置 AppBar:

Things you should know: The activity mustn't have a AppBar set on AndroidManifest.xml:

android:theme="@style/AppTheme.NoActionBar"

如果您注意到 NavigationView 标签中的 app:menu="@menu/activity_main_drawer",片段名称应该与 中的片段名称相同mobile_navigation.xml:

If you notice app:menu="@menu/activity_main_drawer" in the NavigationView tag, the fragment names should be the same that they are inside the mobile_navigation.xml:

<group android:checkableBehavior="single">
        <item
            android:id="@+id/homeFragment"
            android:icon="@drawable/ic_menu_camera"
            android:title="@string/menu_home" />
        <item
            android:id="@+id/galleryFragment"
            android:icon="@drawable/ic_menu_gallery"
            android:title="@string/menu_gallery" />
        <item
            android:id="@+id/slideshowFragment"
            android:icon="@drawable/ic_menu_slideshow"
            android:title="@string/menu_slideshow" />
        <item
            android:id="@+id/toolsFragment"
            android:icon="@drawable/ic_menu_manage"
            android:title="@string/menu_tools" />
    </group>

    <item android:title="Communicate">
        <menu>
            <item
                android:id="@+id/shareFragment"
                android:icon="@drawable/ic_menu_share"
                android:title="@string/menu_share" />
            <item
                android:id="@+id/sendFragment"
                android:icon="@drawable/ic_menu_send"
                android:title="@string/menu_send" />
        </menu>
    </item>

</menu>

这样,通过下面将要解释的内容,就无需调用 onCreateOptionsMenu 来检测点击.Android 团队已经为我们解决了这个问题.关注下方.

This way, with what is going to be explained below there will be no need to call for onCreateOptionsMenu to detect the clicks. Android team has already solved that for us. Follow below.

到目前为止,这与我们实际设置的通常抽屉没有太大区别.但是,我们需要在应用程序的逻辑部分进行一些配置.所以让我们打开MainActivity.kt.首先你需要这些:

Until now, this doesn't differ too much from the usual drawer set up we actually do. But, there are some configurations we would need to do in the logic part of the app. So let's open MainActivity.kt. First you will need these:

  private var appBarConfiguration: AppBarConfiguration? = null
  private var drawerLayout: DrawerLayout? = null
  private var toolbar: Toolbar? = null
  private var navController: NavController? = null

之后在您的 onCreate 方法中:

After that in your onCreate method:

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        toolbar = findViewById(R.id.toolbar)
        setSupportActionBar(toolbar) //set the toolbar

        drawerLayout = findViewById(R.id.drawer_layout)
        val navView: NavigationView = findViewById(R.id.nav_view)
        navController = findNavController(R.id.nav_host_fragment)
        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.homeFragment,
                R.id.galleryFragment,
                R.id.slideShowFragment,
                R.id.toolsFragment,
                R.id.shareFragment,
                R.id.sendFragment,
                R.id.loginFragment,
                R.id.phoneConfirmationFragment
            ), drawerLayout
        )

        setupActionBarWithNavController(navController!!, appBarConfiguration!!) //the most important part
        navView.setupWithNavController(navController!!) //the second most important part

      //other things unrelated
    }

让我们看看这里发生了什么:

Let's see what's going on here:

首先,您需要对 navController 的引用.AppBarConfiguration 只是一个类,其中包含将作为顶级目的地打开的片段.这意味着将在它们之后打开的片段将从片段返回堆栈中释放当前片段.告诉 AppBarConfiguration 我们还有一个抽屉很重要(在构造函数中作为参数传递).

First you would need a reference to the navController. The AppBarConfiguration is just a class which holds the fragments that are going to be opened as top level destinations. Which means that the fragment which is going to be opened after them would release the current one from the fragment back stack. It's important to tell to the AppBarConfiguration that we have a drawer also (passed as a parameter in the constructor).

在下面你会有一个名为 onSupportNavigateUp() 的方法:

Down below you would have a method called onSupportNavigateUp():

override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment)
        return navController.navigateUp(appBarConfiguration!!) || super.onSupportNavigateUp()
    }

此方法与向上后退按钮有关.但是如果你有抽屉导航,你就不会太需要它.当你在 backstack 上添加了很多片段(或至少两个)时,这真的很方便.

This method has to do with the up back button. But you won't need it too much if you have drawer navigation. This really comes in handy when you have a lot of fragments added on the backstack (or at least two).

可以用一个 Activity 完成所有事情吗?

Can everything be done with one Activity?

是的,绝对!但是在条件导航方面仍然需要做更多的工作.就像当您想显示不属于抽屉应用程序的片段时一样.但是谷歌仍然在这方面取得了巨大的进步.您可以在此处参考条件导航.

Yes, definitely! but still it requires a little bit more work when it comes to conditional navigation. Like when you want to show fragments which are not part of your drawer app. But still Google has done a huge progress with it. You can refer to conditional navigation here.

如何仅使用一个 Activity 处理工具栏可见性和具有动态工具栏可见性的片段.此外,还有我需要关闭抽屉并使其无法访问的碎片.

How do I handle toolbar visibility with just one Activity and fragments which have a dynamic toolbar visibility. Also, there are fragments which I need to close the drawer and make it inaccessible.

您可以使用 navController 中的 addOnDestinationChangedListener:

You can use addOnDestinationChangedListener from the navController:

navController.addOnDestinationChangedListener { _, destination, _ ->
            when (destination.id) {
                R.id.loginFragment, R.id.registerFragment, R.id.phoneConfirmationFragment -> {
                    toolbar?.visibility = View.GONE
                    drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED)
                }
                else -> {
                    toolbar?.visibility = View.VISIBLE
                    drawerLayout?.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED)
                }
            }
        }

现在您的应用上有一个抽屉和导航组件.

Now you have a drawer and navigation component on your app.

这篇关于如何在 Android 中使用 Navigation Drawer 设置导航组件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆