Android 官方 Navigation Drawer

Wafer Li ... 2016-11-08 Android
  • Android
  • 旧文仓库
大约 5 分钟

1. 概述
2. 添加依赖
3. 设计 layout/activity_main.xml
4. 构建 layout/drawer_header.xml
5. 定义 menu/drawer_item.xml
6. 显示汉堡包图标
7. 使状态栏透明
7.1 去除 Actionbar
7.2 v21 增加关于状态栏的属性
7.3 设置 DrawerLayout 使用 fitsSystemWindow
7.4 补充:动态改变 status bar 颜色
8. 总结

# 1. 概述

Navigation drawer 作为 Android Material Design 中主流的一种导航方式,当然受到 Google 的重视,所以,作为 MD 设计推出的实现部分,Android 更新了 support library 增加了关于 Navigation Drawer 的支持。

下面就来看看如何进行 Navigation Drawer 的构建。

# 2. 添加依赖

官方的 Navigation Drawer 需要用到 DrawerLayoutNavigationView,它们都在 support design 包下。

compile 'com.android.support:design:24.2.1'
1

这里不使用最新的 25.0.0 的原因在于,最新版在 UI Editor 渲染时存在 bug。Google 不愧是世界上最伟大的半成品公司。

# 3. 设计 layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
    android:id="@+id/drawer_layout"
    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"
    android:fitsSystemWindows="true"
    tools:context="com.wafer.toy.github_client.ui.activity.MainActivity">

    <!-- Your main content -->


    <android.support.design.widget.NavigationView
        android:id="@+id/navigation_drawer"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/drawer_header"
        app:menu="@menu/drawer_item"/>
</android.support.v4.widget.DrawerLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

需要注意的是,DrawerLayout 是布局的根目录,同时要设置 fitsSystemWindows="true",否则,将会覆盖掉顶部状态栏。

还有,注意要设置 NavigationViewlayout_gravity="start",否则不会生效。

# 4. 构建 layout/drawer_header.xml

一般来说,Nav Drawer 都需要有一个 header 来存放用户头像等等有关用户账户的概览信息。

所以我们还要定义一个 header 的布局,然后像上面一样,将其赋予 app:headerLayout

header 的布局注意满足 Material Design (opens new window) 即可;布局样式和摆放不限。

# 5. 定义 menu/drawer_item.xml

是时候给我们的 Nav Drawer 加上一点内容了,通过在 menu/drawer_item.xml 中定义相应的组件即可。

<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/nav_home"
            android:icon="@drawable/ic_drawer_home"
            android:title="@string/nav_home" />
        <item
            android:id="@+id/nav_about"
            android:icon="@drawable/ic_drawer_about"
            android:title="@string/nav_about" />
        <item
            android:id="@+id/nav_settings"
            android:icon="@drawable/ic_drawer_settings"
            android:title="@string/nav_settings" />

        <item
            android:id="@+id/navigation_subheader"
            android:title="@string/nav_sub_header">
            <menu>
                <item
                    android:id="@+id/navigation_sub_item_1"
                    android:icon="@drawable/ic_drawer_about"
                    android:title="@string/nav_sub_item_1" />
                <item
                    android:id="@+id/navigation_sub_item_2"
                    android:icon="@drawable/ic_drawer_home"
                    android:title="@string/nav_sub_item_2" />
            </menu>
        </item>
    </group>
</menu>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

注意,项目的分界通过内嵌的 <menu> 来实现。

需要注意的是,官方的 nav drawer 中的 item 没有 ripple,只有长按才能显示。

最后我们再将这个 menu 赋到 NavgationViewapp:menu="@menu/drawer_item"

# 6. 显示汉堡包图标

Drawer 到这里就完全搭建好了,但是,没有汉堡包图标,用户就不知道我们的应有有个 Nav Drawer。所以,我们就需要给 toolbar 加上一个汉堡包图标来凸显 Nav Drawer 的存在。

在这里,我们需要进入到 java 文件中进行修改了,由于我用的是 Kotlin,这里使用 Kotlin 来做演示。

下面就是增加显示汉堡包的方法:

class MainActivity : BaseActivity() {

    private val actionBarDrawerToggle: ActionBarDrawerToggle by lazy { createActionBarDrawerToggle() }

    override fun initView() {
        initToolbar()
        initActionBarDrawerToggle()
    }

    private fun initActionBarDrawerToggle() {
        drawer_layout.addDrawerListener(actionBarDrawerToggle)
        actionBarDrawerToggle.syncState()
    }

    private fun initToolbar() {
        setSupportActionBar(toolbar)
    }



    private fun createActionBarDrawerToggle(): ActionBarDrawerToggle {
        return ActionBarDrawerToggle(
                this, drawer_layout, toolbar, R.string.open_drawer, R.string.close_drawer)
    }

    override fun getLayoutRes(): Int {
        return R.layout.activity_main
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

首先,使用 DrawerLayout 对象和 toolbar 对象来构建一个 ActionBarDrawerToggle 对象;

然后让 ActionBarDrawerToggle 成为 drawer_layout 的一个接口;

最后设置 actionBarDrawerToggle.syncState() 即可。

# 7. 使状态栏透明

我们已经成功的构建出了一个 Navigation Drawer,但是,其显示出来的效果是这样的

而官方的 MD 规范上,状态栏的效果是半透明的。

所以,我们还要做一些额外的步骤来让我们的 Nav Drawer 更符合规范。

# 7.1 去除 Actionbar

这个步骤通常已经在初步搭建构架的时候就完成了。也就是说为 style.xml 增加如下两项:

<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
1
2

并且继承 Theme.AppCompact.Light.DarkActionBar

# 7.2 v21 增加关于状态栏的属性

value-21/style.xml 中,增加另外的两项:

<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
<item name="android:windowDrawsSystemBarBackgrounds">true</item>
<item name="android:statusBarColor">@android:color/transparent</item>
1
2
3
4

# 7.3 设置 DrawerLayout 使用 fitsSystemWindow

<android.support.v4.widget.DrawerLayout
    ...
    android:fitsSystemWindows="true"
    app:insetForeground="@color/inset_color"
    >
1
2
3
4
5

OK,到这里就大功告成了!

# 7.4 补充:动态改变 status bar 颜色

如果你想动态改变状态栏颜色的话,也有相应的 Java 接口。

drawerLayout.setStatusBarBackgroundColor(ContextCompat.getColor(this, R.color.wierd_green));

drawerLayout.setScrimColor(ContextCompat.getColor(this, R.color.wierd_transparent_orange));
1
2
3

# 8. 总结

这样构造出来的 Nav Drawer 和 MaterialDrawer 不同的一个地方在于,Nav Drawer 是在设计层面上进行修改,而 MaterialDrawer 是在代码层面上进行修改,侵入性不强,不过也较为麻烦。

总的来说,如果要快速搭建,则选择 MaterialDrawer; 但是要选择使用清真的写法,那么 Nav Drawer 则会更好。