ANDROID – TOOLBAR 上的 NAVIGATION DRAWER(转)

在 Material Design 釋出後,Google 也開始陸續更新了 Google app 的介面,讓大家有個範例可以看。而過去大力推動的 actionbar 自然而然也成了眾開發者觀注的部份;其中的 up button 的設定在前一篇所介紹的 Toolbar 也已看到。這邊還未提到的一個部份是 material design 中有提到的人機互動效果,簡言之,就是讓使用者明顯地感受到在操作 app 時,可以獲得明顯的回應,從而得到豐富地操作體驗感;因此,在剛開始釋出的幾支 Google app 裡,大家一定都有留意到開啟 navigation drawer 時,up button 從選單圖示 (menu/hamburger icon) 旋轉成倒退圖示 (back icon) 的新效果了!

先來看到效果:

相信大家也都會很好奇這個效果要如何實作,會不會很麻煩?所幸,這個效果,被放進 support v7 之中,我們只要拿來用即可。在本篇中將分下列幾個部份,來帶大家無痛地寫出這個效果來。

  1. 實作
  2. Material design guideline 定義的 Side Drawer
  3. 其他議題

本篇所使用到的程式碼,請到 Github 下載。

1. 實作



我們馬上就開始從 navdrawer_deom_checkpoint0 開始 (這份程式碼其實就是在 Toolbar Step By Step – 調色 階段完成的toolbar_demo_checkpoint2),

在 activity_main.xml 中加入 DrawerLayout

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

33

34

35

36

37

38

39

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

xmlns:tools="http://schemas.android.com/tools"

android:layout_width="match_parent"

android:layout_height="match_parent"

tools:context=".MainActivity">

<android.support.v7.widget.Toolbar

android:id="@+id/toolbar"

... />

<android.support.v4.widget.DrawerLayout

android:id="@+id/drawer"

android:layout_height="match_parent"

android:layout_width="match_parent"

android:layout_below="@+id/toolbar">

<!-- Content -->

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="match_parent">

...

</RelativeLayout>

<!-- Side Drawer -->

<LinearLayout

android:id="@+id/drawer_view"

android:layout_width="@dimen/navdrawer_width"

android:layout_height="match_parent"

android:layout_gravity="start"

android:background="#88FFFFFF"

android:orientation="vertical">

</LinearLayout>

</android.support.v4.widget.DrawerLayout>

</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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

private DrawerLayout mDrawerLayout;

private ActionBarDrawerToggle mDrawerToggle;

@Override

protected void onCreate(Bundle savedInstanceState) {

...

// 打開 up button

getSupportActionBar().setDisplayHomeAsUpEnabled(true);

mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer);

// 實作 drawer toggle 並放入 toolbar

mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, toolbar, R.string.drawer_open, R.string.drawer_close);

mDrawerToggle.syncState();

mDrawerLayout.setDrawerListener(mDrawerToggle);

}

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

完整程式碼請見:navdrawer_demo_checkpoint1

2. Side Drawer



在 Material Design 導覽文件釋出之初,其實是沒有看到側邊欄的相關說明,一直到 2014.10 才以「Side Nav」之名,加述於導覽文件之中。而這個定義中的 Side Nav 畫面,其實跟原本在 actionbar 的階段是不太一樣的,drawer layout 會壓在 toolbar 上,如下圖:

目前在 Google app 的介面中,還是以前一種為多,而現下 (2014.10) 如同 material  design 在 side nav 呈現的介面還不多。

接下來就用 navdrawer_demo_checkpoint1 做為這個階段的開始往下進行,需要調整就只有介面 (activity_main.xml) 的部份:

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

33

34

<android.support.v4.widget.DrawerLayout

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

xmlns:tools="http://schemas.android.com/tools"

android:id="@+id/drawer"

android:layout_height="match_parent"

android:layout_width="match_parent"

tools:context=".MainActivity">

<!-- Content -->

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="match_parent">

<android.support.v7.widget.Toolbar

android:id="@+id/toolbar"

... />

...

</RelativeLayout>

<!-- Side Drawer -->

<LinearLayout

android:id="@+id/drawer_view"

android:layout_width="@dimen/navdrawer_width"

android:layout_height="match_parent"

android:layout_gravity="start"

android:clickable="true"

android:background="#88FFFFFF"

android:orientation="vertical">

</LinearLayout>

</android.support.v4.widget.DrawerLayout>

將 DrawerLayout 改到這個 layout 的 root 層,並將 toolbar 移到 content 的 layout 中,這樣就可以達到這樣的效果了。

需要注意的是地方在 Side 的 layout 要設定 clickable 的屬性設定為 true,否則會在側邊欄打開的狀況下,還能按到位於介面下方的 up button。

But!人生就是這個 but!

在前一陣子,Google 的設計師為 Google I/O 2014 設計了另外一種樣式出來,差異請見下圖:

嗯,簡言之,狀態列是半透明的狀態,而側邊欄可以被看到。要調整的地方有二,一在 layout – activity_main.xml:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<android.support.v4.widget.DrawerLayout

...

android:fitsSystemWindows="true"

...>

<!-- Content -->

...

<!-- Side Drawer -->

<LinearLayout

...

android:fitsSystemWindows="true"

... >

</LinearLayout>

</android.support.v4.widget.DrawerLayout>

在 root 層的 drawer layout 跟 side drawer 的 layout 各別加上android:fitsSystemWindows="true" 這個屬性

另外一個要改的地方是在 v21/styles.xml

1

2

3

4

5

<style name="AppTheme" parent="AppTheme.Base">

...

<!--Status bar color-->

<item name="android:statusBarColor">#88009688</item>

</style>

加入一個有透明度的色碼給 android:statusBarColor 這個狀態列顏色設定屬性。

這樣就可以完成這個階段的程式了。

完整程式碼請見:navdrawer_demo_checkpoint2

3. 其他議題



Navigation icon 切換的效果,除了旋轉以外,還有另外一種效果,請看下方的影像:

3.1 Navigation icon effect

左上角的切換效果變成線條的的聚合,同時 icon 的顏色也被改為黑色,這個設定只要在 /res/values/styles.xml 做如下設定

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

<style name="AppTheme.Base" parent="Theme.AppCompat">

...

<!--將新加入的風格 AppTheme.MyDrawerStyle 設定給 drawerArrowStyle 這個屬性-->

<item name="drawerArrowStyle">@style/AppTheme.MyDrawerArrowStyle</item>

</style>

<!--加入一個新的 navigation drarwer 的風格-->

<style name="AppTheme.MyDrawerArrowStyle" parent="Widget.AppCompat.DrawerArrowToggle">

<!--將 spinBars 屬性設定為 false-->

<item name="spinBars">false</item>

<!--設定 drawer arrow 的顏色-->

<item name="color">@android:color/black</item>

</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

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

<!-- Content -->

<RelativeLayout

android:layout_width="match_parent"

android:layout_height="match_parent">

<android.support.v7.widget.Toolbar

...

android:elevation="10dp"

...  />

<TextView

...

android:elevation="10dp"

android:background="@android:color/black"

.../>

</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 的人在本篇中給予留言,做認證嘍  

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

2014/10/29 更新

剛巧,在同一天 Roman Nurik 在官方部落貼出了一篇 android app 的 material design 確認項目表,其中在 Navigation drawer 的部份也很明確的提到,drawer 就是以最新的釋出的樣式為標準,也就是 drawer 會覆蓋在 app bar 之上,被壓於 status bar 之下,最好還可以將 status bar 設定成半套明的樣子。

這樣的定義也有不少人問到,那這樣該 icon 都被蓋住了,要其動態效果何用?這個問題,Roman 在其 G+ 的貼文「Google I/O App Source Updated for Android 5.0 SDK」中做了如此的回應:「there are other situations where that animation can be used, e.g. moving from a top level section to a detail screen. More generally, I’d optimize for consistency and rational layering before optimizing for cool animations.」大抵的意思就是,該動畫還是會有地方可以被使用到,像是從上層 “移動” 到其下一層時。就算定義出很酷的動態效果,還是會以整體的層次感做為優先考量。

總歸來說,navigation drawer 的呈現,就是以下方這張由 Roman 定義好的樣式為標準啦!至於怎麼實作,還請往上看到實作說明嘍 =]


至於為什麼有些有 navigation drawer 的 Google app 未遵從這樣的標準呢?忘了在哪一篇 G+ 裡面有看到,Roman 有回覆說,因為程式架構的關係還在調整,未來會朝這個標準來更新之。

时间: 2024-10-11 21:42:09

ANDROID – TOOLBAR 上的 NAVIGATION DRAWER(转)的相关文章

Android官方终于支持 Navigation Drawer(导航抽屉)模式

在2013 google IO当天,Android团的更新了Support库,新版本(V13)的Support库中新加入了几个比较重要的功能. 添加 DrawerLayout 控件,支持创建  Navigation Drawer模式.可以设置从左边划出菜单或者右边,也可以左右菜单同时存在.    添加 SlidingPaneLayout 控件来支持各种屏幕上的摘要.详情界面模式.比如 Gmail邮件列表和单个邮件详情界面.当在手机上显示的时候,邮件列表和详情界面分别为两个界面:当在平板上显示的时

Creating a Navigation Drawer 创建一个导航抽屉

The navigation drawer is a panel that displays the app’s main navigation options on the left edge of the screen. It is hidden most of the time, but is revealed when the user swipes a finger from the left edge of the screen or, while at the top level

Navigation Drawer详解-Google推出的用来取代Sliding Menu的控件(一

相信Sliding Menu很多人都用过,在Android和iOS的app中,越来越多的开发者都会把自己的菜单界面放在一个列表里,然后让用户通过向右(或者向左)滑动的操作看到应用所有的功能.Google官方的应用也基本都选择了这种交互方式,不同的是,Google使用的是Navigation Drawer,而我们大部分用的还是Sliding Menu. 大家对Sliding Menu这个开源项目可能已经很熟悉了,但是Navigation Drawer我们有些童鞋可能了解的还比较少,它是Google

Android - 基于Toolbar的Navigation Drawer(Material Design)

Material Design已经推出许久,有许多app都已经跟进了,这里也介绍下基于Toolbar的Navigation Drawer是如何实现的. 样式: 实现过程: 1. 在 activity_asdemo.xml 中加入 DrawerLayout <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools=&qu

Android Navigation Drawer(导航抽屉)

Google I/O 2013 Android 更新了Support库,新版本的Support库中新加入了几个比较重要的功能. 添加 DrawerLayout 控件,支持创建  Navigation Drawer模式.可以设置从左边划出菜单或者右边,也可以左右菜单同时存在. 添加 SlidingPaneLayout 控件来支持各种屏幕上的摘要.详情界面模式.比如 Gmail邮件列表和单个邮件详情界面.当在手机上显示的时候,邮件列表和详情界面分别为两个界面:当在平板上显示的时候,则为一个界面. 添

Android - Navigation Drawer

http://www.jianshu.com/p/c8cbeb7ea43a 用Navigation Drawer 和 Navigation View 来实现左右侧滑 Activity里甚至什么都不用写 NavigationDrawer 简介 NavigationDrawer 是 Google 在 Material Design 中推出的一种侧滑导航栏设计风格.说起来可能很抽象,我们直接来看看 网易云音乐 的侧滑导航栏效果 Google 为了支持这样的导航效果,推出一个新控件 -- DrawerL

Android设计和开发系列第二篇:Navigation Drawer(Design)

Navigation Drawer Creating a Navigation Drawer The navigation drawer is a panel that transitions in from the left edge of the screen and displays the app’s main navigation options. Displaying the navigation drawer The user can bring the navigation dr

Android Toolbar使用及Fragment中的Toolbar处理

Toolbar作为ActionBar使用介绍 本文介绍了在Android中将Toolbar作为ActionBar使用的方法.并且介绍了在Fragment和嵌套Fragment中使用Toolbar作为ActionBar使用时需要注意的事项. 使用support library的Toolbar Android的ActionBar每个版本都会做一些改变, 所以原生的ActionBar在不同的系统上看起来可能会不一样.使用support library版本的Toolbar可以让你的应用在多种设备类型上保

Navigation Drawer详解-Google推出的用来取代Sliding Menu的控件(二

第一篇我们就google官方给出的Navigation Drawer demo做了一个简单的介绍,细心的童鞋可能已经发现问题了,google虽然是在support v4中添加的这个控件,但是他给的demo中却使用了ActionBar!ActionBar是在3.0才出现的控件,我们如果想在2.X的版本上同时使用ActionBar和Navigation Drawer,该怎么办呢?http://www.ijiami.cn/treg 其实这个也很简单,我们只需要使用一个开源的library就可以完成了: