Android开发:最详细的 NavigationDrawer 开发实践总结
最详细的 NavigationDrawer 开发实践总结
继前面写的两篇文章之后(有问题欢迎反馈哦):
接着来写写Android系统UI新特性,本文是我对最近开发过程中应用NavigationDrawer 特性的详细总结。本文涉及到的所有代码实现细节,会在文末附上源码地址。有问题欢迎在下方留言讨论 。
NavigationDrawer 简介
NavigationDrawer 是 Google 在 Material Design 中推出的一种侧滑导航栏设计风格。说起来可能很抽象,我们直接来看看 网易云音乐 的侧滑导航栏效果
Google 为了支持这样的导航效果,推出一个新控件 —— DrawerLayout 。而在DrawerLayout 没诞生之前,需求中需要实现侧滑导航效果时,我们必然会选择去选择一些成熟的第三方开源库(如最有名的 SlidingMenu)来完成开发 。效果上,普遍都像手Q 那样:
在对比过 DrawerLayout 和 SlidingMenu 的实现效果后,基于以下的几点,我认为完全可以在开发中使用 DrawerLayout 取代以前的 SlidingMenu:
- 从动画效果上看,你会发现两者仅仅是在移动的效果上有些差别外,其他地方并没有太大的差异
- 在交互效果上,我认为这两者都差不多的,就算你把 网易云音乐 的效果套到了 手Q上,也不会影响到用户的交互
- DrawerLayout 用起来比 SlidingMenu 更简单,代码量更少(往下看就知道了)
- DrawerLayout 是向下兼容的,所以不会存在低版本兼容性问题
- Google 亲儿子,没理由不支持啊!!!!!!
到这里,要是你还没有引入 DrawerLayout 开发的冲动,请继续听我为你好好安利一番。
初识 DrawerLayout
一般情况下,在 DrawerLayout 布局下只会存在两个子布局,一个 内容布局 和 一个侧滑菜单布局,这两个布局关键在于 android:layout_gravity 属性的设置。如果你想把其中一个子布局设置成为左侧滑菜单,只需要设置android:layout_gravity="start" 即可(也可以是 left,右侧滑则为 end 或 right ),而没有设置的布局则自然成为 内容布局 。那么,使用 DrawerLayout 到底有多简单呢,我们先直接看看下面的布局文件
layout/activity_simple_drawer.xml
<?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="match_parent">
<android.support.v4.widget.DrawerLayout
android:id="@+id/simple_navigation_drawer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!--内容视图-->
<include
android:id="@+id/tv_content"
layout="@layout/drawer_content_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!--左侧滑菜单栏-->
<include
layout="@layout/drawer_menu_layout"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="start" />
<!--右侧滑菜单栏-->
<include
layout="@layout/drawer_menu_layout"
android:layout_width="250dp"
android:layout_height="match_parent"
android:layout_gravity="end" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
到此,你在 Activity 里面什么都不用做,就已经完成了下面侧滑效果的实现了,简单到害怕有木有。
在欣赏着 DrawerLayout 简单方便的同时,Google 也为我们提供了 DrawerLayout 很多常用的API,其中包括:打开或关闭侧滑栏、控制侧滑栏的方向、设置滑动时渐变的阴影颜色和监听滑动事件等。
具体详细代码请参加工程中的 SimpleDrawerActivity,此处就不贴代码了。还有一处DrawerLayout 使用的小细节需要温馨提醒一下,有一次,我手误把 DrawerLayout的 android:layout_width 设置成 wrap_content,就出现下面的异常了
遇到过相同情况的童鞋,只需要把 android:layout_width 设置成 match_parent 即可。
再识 NavigationView
在 Google 推出 NavigationDrawer 设计中,NavigationView 和 DrawerLayout是官方推荐的最佳组合。在使用 NavigationView 前,因为它是在 Material Design 的兼容包中,所以需要先在 build.gradle 中引入
compile 'com.android.support:design:23.1.1'
这里因为我工程配置的 compileSdkVersion 是 23 ,所以需要引入com.android.support:design:23.x.x 的版本。需要吐槽的是,这里如果你引入了com.android.support:design:23.1.0 ,工程运行后 NavigationView 会报一个android.view.InflateException:xxxxxx 的错误(又是一个大坑)。
接下来简单的介绍一下 NavigationView 的使用,我们继续看看几个相关布局文件layout/activity_simple_navigation_drawer.xml、layout/navigation_drawer_header.xml、menu/navigation_drawer_menu.xml 和 实现效果:
layout/activity_simple_navigation_drawer.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="NavigationDrawerContent" />
</LinearLayout>
<android.support.design.widget.NavigationView
android:id="@+id/navigation_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/navigation_drawer_header"
app:menu="@menu/navigation_drawer_menu" />
</android.support.v4.widget.DrawerLayout>
layout/navigation_drawer_header.xml
<?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="250dp"
android:background="@color/color_512da8">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_margin="10dp"
android:text="HeaderLayout"
android:textColor="@android:color/white"
android:textSize="18sp" />
</RelativeLayout>
menu/navigation_drawer_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/item_green"
android:icon="@mipmap/green"
android:title="Green" />
<item
android:id="@+id/item_blue"
android:icon="@mipmap/blue"
android:title="Blue" />
<item
android:id="@+id/item_pink"
android:icon="@mipmap/pink"
android:title="Pink" />
</group>
<item android:title="SubItems">
<menu>
<item
android:id="@+id/subitem_01"
android:icon="@mipmap/ic_launcher"
android:title="SubItem01" />
<item
android:id="@+id/subitem_02"
android:icon="@mipmap/ic_launcher"
android:title="SubItem02" />
<item
android:id="@+id/subitem_03"
android:icon="@mipmap/ic_launcher"
android:title="SubItem03" />
</menu>
</item>
<item android:title="SubItems">
<menu>
<item
android:id="@+id/subitem_04"
android:icon="@mipmap/ic_launcher"
android:title="SubItem04" />
<item
android:id="@+id/subitem_05"
android:icon="@mipmap/ic_launcher"
android:title="SubItem05" />
<item
android:id="@+id/subitem_06"
android:icon="@mipmap/ic_launcher"
android:title="SubItem06" />
</menu>
</item>
</menu>
最终得到下面的效果
总的来说,NavigationView 比较关键的属性就只有 app:headerLayout 和app:menu ,它们分别对应效果图中顶部的 紫色区域(layout/navigation_drawer_header.xml) 和 下方的 填充菜单项(menu/navigation_drawer_menu.xml)。其实是用起来也和 DrawerLayout 一样,非常简单。
不实用的 NavigationView
其实谈到 NavigationView,个人认为它设计并不实用,而且是比较呆板的。最直接的一点是,它的菜单图标
第一次运行代码的时候,把我五颜六色的图标居然跑出来这效果,差点没一口水喷在屏幕上。好在代码中可以调用下面这个API
mNavigationView.setItemIconTintList(null);//设置菜单图标恢复本来的颜色
还原菜单图标庐山真面目。(着实看不懂 Google 的设计了...)
其次,是关于菜单相中图标大小和文字间距之类的设置,从 Google 的设计文档来看,
NavigationView 基本已经规定设置好了大小距离,留给我们可以改动的空间并不多。如果你想调整一下菜单的布局宽高之类的,基本是不可能的了(即使可能,也估计非常蛋疼)。所以,目前我基本还没见过国内哪个 app 是直接使用了 NavigationView 来做导航(如果有的话,欢迎告知一下)。
以上关于 NavigationView 不实用,仅是本人的一些看法,如果你有不同看法,欢迎留言讨论。为了加深一下 NavigationDrawer 设计的实践,下面来大致的模仿实现网易云音乐的导航效果。
仿网易云音乐的 NavigationDrawer 实现
先来看看网易云音乐的效果
主要就是一个线性布局的菜单并结合了 Translucent System Bar 的特性(还不知道的童鞋请看我前面写的文章哈),下面就直接看看大致实现的布局文件 :
layout/activity_cloud_music.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/color_cd3e3a">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="65dp"
android:background="@color/color_cd3e3a"
android:gravity="center"
android:text="网易云音乐"
android:textColor="@android:color/white"
android:textSize="18sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white"
android:orientation="vertical">
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="@android:color/white"
android:fitsSystemWindows="true"
android:orientation="vertical">
<ImageView
android:layout_width="match_parent"
android:layout_height="180dp"
android:scaleType="centerCrop"
android:src="@mipmap/topinfo_ban_bg" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:gravity="center_vertical"
android:orientation="horizontal">
<ImageView
android:layout_width="40dp"
android:layout_height="40dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:src="@mipmap/topmenu_icn_msg" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="我的消息"
android:textColor="@android:color/black"
android:textSize="15sp" />
</LinearLayout>
...
...
...
</LinearLayout>
</android.support.v4.widget.DrawerLayout>
最终即可实现类似网易云音乐的效果。
彩蛋
彩蛋一:左上角的导航动画效果实现
经常会看有些 app 的左上角有这些带感的导航动画,之前想要引入这种效果,都是来自第三方的开源代码,诸如下面两个比较有名的:
而现在再也不需要了,Google 推出的 ActionBarDrawerToggle 也能实现这样的效果了,具体查看我在 NavigationDrawerAnimationActivity 中的实现代码
如果你对上面这种动画,效果不满意,也可以考虑一下 material-menu 的另一种实现效果。
彩蛋二:比 NavigationView 更好的选择
前面提到 NavigationView 的不实用性,如果你真的要实现 NavigationView那样的效果,又渴望比较高的自由度。这个功能强大且自由度很高的开源库 MaterialDrawer 应该是个很不错的选择。
总结
到此,对于 NavigationDrawer 的实践总结基本结束。整体给我的感觉是,自从 Material Design 设计开始推出后,Google 推出的这些新控件使用起来更加简单,这能让我们更好的把精力放在编写业务代码上。很多以前需要借助第三方开源库才能实现的效果,现在已经慢慢的不需要了。当然,我们依旧可以去深入的学习这些优秀开源代码,沉淀到更多的干货。这样,小菜也就慢慢成为大牛了。
分享即美德,源代码请看:https://github.com/D-clock/AndroidSystemUiTraining,本篇的主要实现代码如下红圈所示
Android开发:最详细的 NavigationDrawer 开发实践总结的更多相关文章
- Android开发:最详细的 Toolbar 开发实践总结
最详细的 Toolbar 开发实践总结 过年前发了一篇介绍 Translucent System Bar 特性的文章 Translucent System Bar 的最佳实践,收到很多开发者的关注和反 ...
- Android VLC播放器二次开发3——音乐播放(歌曲列表+歌词同步滚动)
今天讲一下对VLC播放器音频播放功能进行二次开发,讲解如何改造音乐播放相关功能.最近一直在忙着优化视频解码部分代码,因为我的视频播放器需要在一台主频比较低的机器上跑(800M主频),所以视频解码能力受 ...
- Android高手速成--第四部分 开发工具及测试工具
第四部分 开发工具及测试工具 主要介绍和Android开发工具和测试工具相关的开源项目. 一.开发效率工具 Json2Java根据JSon数据自动生成对应的Java实体类,还支持Parcel.Gson ...
- 敏捷软件开发:原则、模式与实践——第14章 使用UML
第14章 使用UML 在探索UML的细节之前,我们应该先讲讲何时以及为何使用它.UML的误用和滥用已经对软件项目造成了太多的危害. 14.1 为什么建模 建模就是为了弄清楚某些东西是否可行.当模型比要 ...
- Android SDK +Eclipse+ADT+CDT+NDK 开发环境在windows 7下的搭建
Android SDK+Eclipse+ADT+CDT+NDK 开发环境在windows 7下的搭建 这几天一直在研究 Android SDK C/C++平台的搭建,尽管以前有成功在Windows ...
- Android安装 sdk+jdk+Eclipse+Adt开发工具
根据别人提供的手册和安装过程体验加以更新和详细描述 安装Android开发工具 开发Android应用程序的门坎并不高,因为Google已经为Android应用程序开发提供了免费而且跨平台的集成开发环 ...
- 腾讯云安全:开发者必看|Android 8.0 新特性及开发指南
欢迎大家关注腾讯云技术社区-博客园官方主页,我们将持续在博客园为大家推荐技术精品文章哦~ 背景介绍 谷歌2017 I/O开发者大会今年将于5月17-19日在美国加州举办.大会将跟往年一样发布最新的 A ...
- 【毕业设计】基于Android的家校互动平台开发(内含完整代码和所有文档)——爱吖校推(你关注的,我们才推)
☆ 写在前面 之前答应大家的毕业答辩之后把所有文档贡献出来,现在答辩已过,LZ信守承诺,把所有文档开源到了GitHub(这个地址包含所有的代码和文档以及PPT,外层为简单的代码).还望喜欢的朋友们,不 ...
- 【Scrum】-NO.40.EBook.1.Scrum.1.001-【敏捷软件开发:原则、模式与实践】- Scrum
1.0.0 Summary Tittle:[Scrum]-NO.40.EBook.1.Scrum.1.001-[敏捷软件开发:原则.模式与实践]- Scrum Style:DesignPattern ...
随机推荐
- dp 0-1背包问题
0-1背包的状态转换方程 f[i,j] = Max{ f[i-1,j-Wi]+Pi( j >= Wi ), f[i-1,j] } f[i,j]表示在前i件物品中选择若干件放在承重为 j 的背包 ...
- 简谈HashMap、HashTable的区别
简单的说HashMap是HashTable的轻量级实现,即非线程安全的实现,他们的主要区别概述为: HashMap HashTable (1)允许键和值为null 不允许键或值为null (2)不是 ...
- struts2不能通过ONGL方式取出request中的Atrribute
请看下面一个很简单的Action package com.ahgw.main.action; import org.springframework.stereotype.Controller; /** ...
- Guava的一些总结
guava是java API蛋糕上的冰激凌(精华). 源码包的简单说明: com.google.common.annotations:普通注解类型. com.google.common.base: ...
- Error: opening registry key 'Software\JavaSoft\Java Runtime Environment' Error: could not find java.dll
java -jar yxCollector-1.1.0.jarError: opening registry key 'Software\JavaSoft\Java Runtime Environme ...
- eclipse 中使用等宽字体 inconsolata
一直以来,就感觉使用 eclipse 时的那几种字体很难看,而且非等宽,空格宽度很小,排版很乱. 搜索并试用了一下,发现了字体inconsolata. 这是一个很适合编程的字体,效果如下: 非常漂亮. ...
- 利用腾讯企业邮箱开放API获取账户未读邮件数初探
公司一直使用腾讯提供的免费企业邮箱服务,今天用管理员帐户登录后发现,原来现在腾讯的企业邮箱也开放了部分API 你可以通过开放接口实现以下功能: 数据同步 数据同步可以帮助你同步部门成员信息,你还可以创 ...
- simulink下直接代码生成
连接好DSP,打开Matlab,首先必须要更改环境,要不不能编译通过 输入C2000lib,打开库, 在C2833X DSP Chip Support中添加外设,然后在C2000 Target Pre ...
- C++之函数指针
函数指针常用的有三类 1.指向普通函数的函数指针 2.指向类中静态成员函数的函数指针 3.指向类的成员函数的函数指针 一.指向普通函数的函数指针 #include <iostream> u ...
- UVa816 Abbott's Revenge
Abbott's Revenge Time limit: 3.000 seconds Abbott’s Revenge Abbott’s Revenge The 1999 World FinalsC ...