Android – Toolbar 上的 Navigation Drawer

来源:互联网 发布:华为的程序员 编辑:程序博客网 时间:2024/06/11 09:13

来源 http://blog.mosil.biz/2014/10/navigation-drawer-on-toolbar/

编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识、前端、后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过!

ToolBar的基础知识请先阅读:android:ToolBar详解(手把手教程)

在 Material Design 发布后,Google 也开始陆续更新了 Google app 的界面,让大家有个范例可以看。而过去大力推动的 actionbar 自然而然也成了众开发者观注的部份;其中的 up button(返回上一级) 的设置在前一篇所介绍的 Toolbar 也已看到。这边还未提到的一个部份是 material design 中有提到的人机交互效果,简言之,就是让使用者明显地感受到在操作 app 时,可以获得明显的回应,从而得到丰富地操作体验感;因此,在刚开始放出的几支 Google app 里,大家一定都有留意到开启 navigation drawer 时,up button 的旋转动画效果。

先来看看效果:

相信大家也都会很好奇这个效果要如何实现,会不会很麻烦?所幸,这个效果,被放进 support v7 之中,我们只要拿來用即可。在本篇中将分下列几个部份,来带大家轻松实现这种效果来。

本篇所使用到的程式码,请到 Github 下载。

1. 实作

我们马上从 navdrawer_deom_checkpoint0 开始 (这份代码其实在 android:ToolBar详解(手把手教程) 一文的自定义颜色一节完成的 toolbar_demo_checkpoint2),

在 activity_main.xml 中加入 DrawerLayout

  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2.                 xmlns:tools="http://schemas.android.com/tools"
  3.                 android:layout_width="match_parent"
  4.                 android:layout_height="match_parent"
  5.                 tools:context=".MainActivity">
  6.                                                                                                                                                                                                                                                                              
  7.   <android.support.v7.widget.Toolbar
  8.     android:id="@+id/toolbar"
  9.     ... />
  10.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  11.   <android.support.v4.widget.DrawerLayout
  12.     android:id="@+id/drawer"
  13.     android:layout_height="match_parent"
  14.     android:layout_width="match_parent"
  15.     android:layout_below="@+id/toolbar">
  16.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  17.     <!-- Content -->
  18.     <RelativeLayout
  19.       android:layout_width="match_parent"
  20.       android:layout_height="match_parent">
  21.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  22.       ...
  23.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  24.     </RelativeLayout>
  25.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  26.     <!-- Side Drawer -->
  27.     <LinearLayout
  28.       android:id="@+id/drawer_view"
  29.       android:layout_width="@dimen/navdrawer_width"
  30.       android:layout_height="match_parent"
  31.       android:layout_gravity="start"
  32.       android:background="#88FFFFFF"
  33.       android:orientation="vertical">
  34.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  35.     </LinearLayout>
  36.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  37.   </android.support.v4.widget.DrawerLayout>
  38.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     
  39. </RelativeLayout>

加入后,请记得将原本在 Toolbar 控件之前的 TextView 放到<!-- Content -->  部份,做 DrawerLayout 其中的內容界面,否则在忘记放入 Content 界面的状況下,关闭侧边栏时,会发生「java.lang.NullPointerException: Attempt to invoke virtual method ‘android.view.ViewGroup$LayoutParams android.view.View.getLayoutParams()’ on a null object reference

这样的错误讯息。

在 drawer_view  中,要记得 layout_gravity 设定成 start  或是 left 。

activity_main.xml 完整程式码请见 github。

再来,就是到 MainActivity.java 中去实作 DrawerLayout,部份程式码如下:

  1. private DrawerLayout mDrawerLayout;
  2. private ActionBarDrawerToggle mDrawerToggle;
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5.   ...
  6.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
  7.   // 打開 up button
  8.   getSupportActionBar().setDisplayHomeAsUpEnabled(true);
  9.   mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer);
  10.   // 實作 drawer toggle 並放入 toolbar
  11.   mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);
  12.   mDrawerToggle.syncState();
  13.   mDrawerLayout.setDrawerListener(mDrawerToggle);
  14. }

完成后,就可以看到如上方影像一样的效果了!

完整程式码请见:navdrawer_demo_checkpoint1

2. Side Drawer

一开始,Material Design 设计文档   中,其实是没有看到侧边栏的相关说明,一直到 2014.10 才以「Side Nav」之名,加述于导览文件之中。而这个定义中的 Side Nav 画面,其实跟原本在 actionbar 的阶段是不太一样的,drawer layout 会压在 toolbar 上,如下图:

NavDrawer over toolbar

目前在 Google app 的界面中,还是以前一种为多,而现下 (2014.10) 如同 material  design 在 side nav 呈现的界面还不多。

接下来就用 navdrawer_demo_checkpoint1 做为这个阶段的开始往下进行,需要调整就只有界面 (activity_main.xml) 的部份:

  1. <android.support.v4.widget.DrawerLayout
  2.   xmlns:android="http://schemas.android.com/apk/res/android"
  3.   xmlns:tools="http://schemas.android.com/tools"
  4.   android:id="@+id/drawer"
  5.   android:layout_height="match_parent"
  6.   android:layout_width="match_parent"
  7.   tools:context=".MainActivity">
  8.   <!-- Content -->
  9.   <RelativeLayout
  10.     android:layout_width="match_parent"
  11.     android:layout_height="match_parent">
  12.     <android.support.v7.widget.Toolbar
  13.       android:id="@+id/toolbar"
  14.       ... />
  15.     ...
  16.   </RelativeLayout>
  17.   <!-- Side Drawer -->
  18.   <LinearLayout
  19.     android:id="@+id/drawer_view"
  20.     android:layout_width="@dimen/navdrawer_width"
  21.     android:layout_height="match_parent"
  22.     android:layout_gravity="start"
  23.     android:clickable="true"
  24.     android:background="#88FFFFFF"
  25.     android:orientation="vertical">
  26.   </LinearLayout>
  27. </android.support.v4.widget.DrawerLayout>

将 DrawerLayout 改到这个 layout 的 root 层,并将 toolbar 移到 content 的 layout 中,这样就可以达到这样的效果了。
需要注意的是地方在 Side 的 layout 要设定 clickable 的属性设定为 true,否则会在侧边栏打开的状况下,还能按到位于界面下方的 up button。
But!人生就是这个 but!

在前一阵子,Google 的设计师为 Google I/O 2014 设计了另外一种样式出来,差异请见下图:

NavDrawer

嗯,简言之,状态栏是半透明的状态,而侧边栏可以被看到。要调整的地方有二,

一在 layout – activity_main.xml:

  1. <android.support.v4.widget.DrawerLayout
  2.   ...
  3.   android:fitsSystemWindows="true"
  4.   ...>
  5.   <!-- Content -->
  6.   ...
  7.   <!-- Side Drawer -->
  8.   <LinearLayout
  9.     ...
  10.     android:fitsSystemWindows="true"
  11.     ... >
  12.   </LinearLayout>
  13. </android.support.v4.widget.DrawerLayout>

在 root 层的 drawer layout 跟 side drawer 的 layout 各别加上 android:fitsSystemWindows="true" 这个属性
另外一个要改的地方是在 v21/styles.xml

  1. <style name="AppTheme" parent="AppTheme.Base">
  2.   ...
  3.   <!--Status bar color-->
  4.   <item name="android:statusBarColor">#88009688</item>
  5. </style>

加入一个有透明度的色码给 android:statusBarColor 这个状态列颜色设定属性。

这样就可以完成这个阶段的程式了。

完整程式码请见:navdrawer_demo_checkpoint2


3. 其他议题

Navigation icon 切换的效果,除了旋转以外,还有另外一种效果,请看下方的影像:

3.1 Navigation icon effect

左上角的切换效果变成线条的的聚合,同时 icon 的颜色也被改为黑色,这个设定只要在 /res/values/styles.xml 做如下设定


  1. <style name="AppTheme.Base" parent="Theme.AppCompat">
  2.                                                                                                                                                                                                                                                                              
  3.   ...
  4.   <!--將新加入的風格 AppTheme.MyDrawerStyle 設定給 drawerArrowStyle 這個屬性-->
  5.   <item name="drawerArrowStyle">@style/AppTheme.MyDrawerArrowStyle</item>
  6. </style>
  7. <!--加入一個新的 navigation drarwer 的風格-->
  8. <style name="AppTheme.MyDrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">
  9.   <!--將 spinBars 屬性設定為 false-->
  10.   <item name="spinBars">false</item>
  11.   <!--設定 drawer arrow 的顏色-->
  12.   <item name="color">@android:color/black</item>
  13. </style>

先加入针对 navigation icon 设定的风格: AppTheme.MyDrawerArrowStyle ,其继承自 Widget.AppCompat.DrawerArrowToggle 这个风格。

以本范例来说,这个风格裡设定了两个属性:

   spinBars
       旋转效果
       false。由此可之,其预设的旋转效果预设值就是 true 了。
   color
       设定 navigation icon 的颜色。

增加后,再回到 AppTheme.Base 风格中,将此风格设定给 drawerArrowStyle 即可看到效果了。

3.2 Shadows

在影像中,大家应该可以看到,这个范例中还有一处跟之前不同了,内容为 Hello world! 的 TextView 变成黑色了!哦!当然不是要为各位介绍这个以前就有属性。要请各位留意的是在 TextView 周围有一圈淡淡的影子,还有在 Toolbar 也因为下方的影子,看起来较有立体感。而这也就是在 Material design 中有提到的其中一个部份:Shadows。

在过去这个效果需要自己去设定 drawable,现在只要设定个属性即可。请到 activity_main.xml 中

  1. <!-- Content -->
  2. <RelativeLayout
  3.   android:layout_width="match_parent"
  4.   android:layout_height="match_parent">
  5.   <android.support.v7.widget.Toolbar
  6.     ...
  7.     android:elevation="10dp"
  8.     ...  />
  9.   <TextView
  10.     ...
  11.     android:elevation="10dp"
  12.     android:background="@android:color/black"
  13.     .../>
  14. </RelativeLayout>

最主要就是针对 android:elevation 这个属性设定,而这个属性的意义也如同其字面的意义,他是在承述相较于底层的高度而被创造出来的阴影。而另外,在这段程式码中,特别将 TextView 中的 android:background 也列出来的原因,就是要让大家知道,android:elevation 这个属性要能够生效,该介面元件的背景属性也需要设定哦!

完整程式码请见:navdrawer_demo_checkpoint3

4. 一点想法

新的 navigation drawer 在 material design 的 side nav 裡有著跟过去不同的样式,而在 Google app 中,包含文中提到那种新的呈现样式算来,共有三重风格。这应该也意谓著,以 Google 在 side nav 在 android app 的呈现上,给予了这些弹性在。换句话说,这样看来,目前看到的这三种样式在 android app 上来看,都可以算是 material design。

也许有人会问,那导览文件是写好玩的吗?以个人的观点来看,那个的确是一个规范,是 Google 想要在不同的平台上有一个共通的范畴得以依循。因此,相信未来在 Google 的产品中,于 web、iOS 以及其他装置的介面,都会以 material design 做为标准,而设计出统一的 Google app 的体验。

而在 android 装置上,嘿嘿…毕竟是 Google 定义的嘛~那自然这部份的弹性就多于其他平台喽。所以,私以为就别太过纠结于导览文件上的定义,只要符合目前所看到的三种样式,应该都可以被视 android 装置上的 material design 啦。大家也可以放宽心的运用这三种样式去做 android app 的设计喽。

当然,以上纯粹个人观点,不代表官方立场,除非有 Google 的人在本篇中给予留言,做认证喽 :

最後,附上本篇所有範例的程式連結,還請大家多多指教嘍。

0 0
原创粉丝点击