安卓组件学习——NavigationView导航视图

1,853 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 18 天,点击查看活动详情

前言

日新计划可真头疼,每天更文养成习惯是好,但有时候没思路就很烦,回到正题,本篇回到很久之前的组件学习(安卓UI设计开发——Material Design(BottomSheetDialogFragment篇) - 掘金 (juejin.cn)),这次我们来看看许多APP首页常用的NavigationView——滑动菜单如何使用。

2/22 更正:NavigationView为导航视图,DrawerLayout为抽屉布局,一起组合成滑动菜单(实现侧滑交互体验)

733c1e864882815b26a38f1520a843a.jpg

正篇

首先,使用NavigationView前我们先创建一个新项目,我这里为了学习这些组件,命名为MaterialDemo,作为我们学习Materia组件的项目,然后因为要使用Material库的NavigationView,所以我们项目的app目录下的build.gradle文件中的dependencies闭包中添加下面依赖:

implementation 'com.google.android.material:material:1.8.0'
implementation 'de.hdodenhof:circleimageview:3.1.0'

其中第二个依赖是我们导入的开源项目CircleImageView,这可以让我们更容易实现图片圆形化,也就是这个滑动菜单栏上圆形头像的形成。

当然,新建的是Kotlin安卓空Activity项目,我们采用了ViewBinding,所以同时也要在该文件下启用ViewBinding,位置在android闭包中:

buildFeatures {
    viewBinding = true
}

sync Gradle(同步 Gradle)完成后,我们再把res/values/theme.xml文件AppThemeparent主题换为Theme.MaterialComponents.Light.NoActionBar,用来适配我们的Material库组件:

image.png

我们还得事先准备几张图片备用(按钮,头像等),这里我放在了drawable-xxhdpi目录下,当然如果有需要可以到文末我的Github项目中找:

image.png

接着,我们在res目录下创建新的名为menu文件夹(和之前文章安卓开发基础——Menu菜单的使用 - 掘金 (juejin.cn)一样):

image.png

image.png

再在这个文件夹上右击->New->Menu resource file ,创建一个nav_menu.xml文件,添加下面的代码:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <group android:checkableBehavior="single">
        <item
            android:id="@+id/navCall"
            android:icon="@drawable/nav_call"
            android:title="Call" />
        <item
            android:id="@+id/navFriends"
            android:icon="@drawable/nav_friends"
            android:title="Friends" />
        <item
            android:id="@+id/navLocation"
            android:icon="@drawable/nav_location"
            android:title="Location" />
        <item
            android:id="@+id/navMail"
            android:icon="@drawable/nav_mail"
            android:title="Mail" />
        <item
            android:id="@+id/navTask"
            android:icon="@drawable/nav_task"
            android:title="Tasks" />
    </group>
</menu>

上面代码中我们加了一个group标签,并把其中的checkableBehavior属性设置为single,这样就能让菜单项变为只可以单选。 然后我们就能预览到这个菜单样式,这就是我们即将用的具体的菜单项:

image.png

但NavigationView样式不是这个预览到的,因为有菜单项这样还是不够的,我们还需要准备一个herderLayout用于显示NavigationView的头部布局,这个布局可以按照需求来定制,这里我们就构建了头像、用户名和邮箱地址这三项,这个布局我们直接在layout目录正常创建布局文件就行,我们这里创建一个名为nav_header的XML布局文件:

image.png 该文件代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="180dp"
    android:padding="10dp"
    android:background="?attr/colorPrimary">

    <de.hdodenhof.circleimageview.CircleImageView
        android:id="@+id/iconImage"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:src="@drawable/nav_icon"
        android:layout_centerInParent="true" />

    <TextView
        android:id="@+id/mailText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="tonygreendev@gmail.com"
        android:textColor="#FFF"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/userText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/mailText"
        android:text="Tony Green"
        android:textColor="#FFF"
        android:textSize="14sp" />

</RelativeLayout>

我们使用了相对布局(RelativeLayout)作为最外层布局,其中CircleImageView就是之前加依赖提到的开源控件,将我们的图片圆形化,和ImageView用法一样,这里我们用于构建圆形的头像图片,且设为居中,还有两个TextView分别就是我们的用户名和邮箱地址,用相对布局属性定位即可。

这些做完后,我们的准备阶段就完成了,接下来我们开始使用NavigationView控件:

我们先把布局添加NavigationView:

<?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"
    android:id="@+id/drawerLayout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <FrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        
        <androidx.appcompat.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
    </FrameLayout>
            

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/navView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:menu="@menu/nav_menu"
        app:headerLayout="@layout/nav_header"/>

</androidx.drawerlayout.widget.DrawerLayout>

Activity中:

package com.example.materialdemo

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.materialdemo.databinding.ActivityMainBinding

class MainActivity : AppCompatActivity() {

    lateinit var binding: ActivityMainBinding
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        setSupportActionBar(binding.toolbar)

        supportActionBar?.let {
            it.setDisplayHomeAsUpEnabled(true)
            it.setHomeAsUpIndicator(R.drawable.ic_menu)
        }
        binding.navView.setCheckedItem(R.id.navCall)
        binding.navView.setNavigationItemSelectedListener {
            binding.drawerLayout.closeDrawers()
            true
        }
    }
}

最终效果:

36ef295afdeec85f9a5cb6a449700d38.gif

这里一开始忘记加我的项目地址了,现在补上:GitHub - ObliviateOnline/MaterialDemo: Material库组件学习

总结

今天学了NavigationView,结果忘记写前面的滑动菜单DrawerLayout和标题栏Toolbar控件了,下一篇就把前面的构建过程给理一遍。