Android 分享會:Material Design 在 Android 中的應用

下位子發表於2017-12-27

前言

我剛來這個公司的時候,每個週三都會有分享會,主題自定,分享物件儘量是面向大眾,一開始覺得不錯,但是到後面發現分享的內容不是那麼有營養,而且積極性不是很高,都是當做任務進行分享。 程式設計師因為較為靦腆,分享的人較少,大部分都是客戶部、分析部或者推广部的分享,久而久之,氛圍就比較消極。

為了提高我們們程式設計師發言的積極性,增添技術部的溝通氛圍,決定之前的分享形式不變,但是改為月末一次,技術部的分享每週一次。主題可以是當前部門的相關技術,當然最好是能夠讓大眾聽懂。分享時能夠積極討論,最終目的提高自身的軟實力,我們們程式設計師不能只知道敲程式碼,是吧?

那麼,輪到我分享了,其實一個月之前就已經通知我讓我準備分享,因為公司有個交易專案要上線,比較繁忙,就沒太抽出時間準備,直到上個星期五才抽出週末的時間準備。

準備

說完那麼多廢話,開始進入正題。最終決定分享主題為『Material Design In Android』。因為之前畢設專案趣聞中有用到「Support Design」庫中的控制元件,所以寫起來會順手一點。我分三部分準備:

  1. APP準備
  2. 文件準備
  3. Keynote準備

一、APP準備

專案已經上傳到GitHub上:AndroidMD

執行效果

MD.gif

花了兩個多小時做了這個APP,功能簡單,主題明確。

先說說完成這個APP的事前準備:

1. 主題

主題是最近非常火的「終結者2:審判日」

2. 資料

資料是自己在本地寫的json資料,很是尷尬,然後部署到七牛雲上。地址是:WeaponInfo

3. 語言

用的語言是之前學的KotlinKotlin學習筆記

4. 風格

整體的風格就是我這次分享的主題 Material Desing風格。

二、整體內容結構的準備

在做PPT之前,先把結構搭好,並且把PPT的內容先準備好,到時候直接就可以複製到PPT中。

整體結構:

  1. 什麼是 Material Design
  2. Material Desing的特點
  3. 從四個特點結合Android的應用剖析
  4. 在我的公司「口袋」專案中的應用

當然內容需要看官方的文件和其他資料加上總結才能完成,所以在此感謝一下文章的幫助:

Material Design 學習筆記

Material Design 官網介紹文件

Material Design 中文介紹

Material Design in Android Developer

三、PPT 的準備

有了之前內容的編寫,做PPT就方便一點。但是因為剛買的MAC,但又不想再裝WPS套餐,於是用的是自帶的keynote,所以使用上會有點生疏。不過,整個PPT製作下來對其使用也熟練了起來。

如果需要的話,可以加個QQ發給你。

1、封面

封面

進入MD官網首頁就是這張圖片。

2、介紹

介紹.gif

MD上擷取的動畫作為入口,大概講解一下MD的基礎概念和特點。

3、特點

特點.gif

這裡抽取了四個點:MaterialElevationColorAnimation進行分析。

4、風格背景

文字採用圓角+陰影進行包裹,至於高度和圓角效果因為時間緊迫,沒有按照嚴格規範進行設定,如果對這方面有要求可以參考官網詳細的規範要求。

image.png

5、動畫效果

說起動畫,為了能夠模仿MD的互動,也是現學現賣了一把。

互動.gif

其實就是背景的放大效果,再加上文字的位移效果。

三、總結

這應該是本人第一次技術分享,除了內容準備的還算充分,分享的過程不是很滿意。本人性格偏內向,平時只默默的擼程式碼、玩遊戲,不願意主動和別人交流,所以不論分享之前還是期間都表現的很緊張,聲音有明顯的顫抖,整體節奏把握的不好,很快。

整個分享過程,感覺自己就是為了將PPT內容放完就等於完成任務似的,導致聽的人迷迷糊糊的,一個點還沒有放完就跳到了另一個點,致使整個分享結束,聽眾吸收的部分很少。在結束後,我們老大 也給了我不少建議:分享的內容不在於多,而在於聽眾吸收了多少,你匆匆忙忙的說完了,底下的人一臉懵逼,這就失去了分享的意義。

確實,技術分享本來的目的不就是為了讓那些對分享主題不熟悉的人能有個大概的瞭解,能夠從中收穫到一些在自己領域中得到應用的技能,這就足夠了。因此,在分享之前,自己要對分享的知識點有個充分的瞭解。在分享時能將每個知識點都有個透徹而又完整的分析,不要追求速度。實話說這次分享確實給我帶了不少的收穫,相信在下次分享中能夠有一個滿意的表現。



我--------------是--------------分--------------割--------------線



Material Design in Android

接下來開始分享這次分享的主要內容,因為MD的介紹和規範在官網上都有非常詳細全面的介紹,所以我就不贅述了,建議自己先看一遍官方網站的介紹,這樣你對MD的理解會更加深入一些。那我把連結再列出一下:

Material Design`官網介紹文件

Material Design 中文介紹

當你把官網的內容大致瀏覽一遍,相信也對MD有個初步的瞭解,當然要想全部弄懂的話,還得需要消化一陣子,畢竟MD的設計規範細緻入微。越讀越能感受到它的妙處,假如你能嚴格按照它的規範進行開發專案,哪怕你不是專業的UI設計師,相信你的產品一定會不難看的。

那接下來就主要介紹一下Material DesingAndroid中應用。。

跟隨著15年Android 5.0的問世,谷歌設計師們還給我們帶來的一系列的具有Material Design風格控制元件。這些控制元件被統一放置在support design庫中,以供開發中使用。使用這些庫的前提是API>=21,當然如果你想在 5.0 一下的裝置這些控制元件的話,需要新增appcompat包進行向下相容。

image.png

我的design版本是26.1.0,上圖大概就是design提供的API,這裡我只做簡單的使用介紹,如果想了解其原理的話,可以看一下官方的介紹。

這麼多我該從何說起呢?我想了下,就按照我做這個小專案,需要的控制元件順序說起吧,這樣也相當於大家跟我一起做出一個具有Material Design風格的APP了。

1、主題

一個專案的開始,你得先確定這個專案的主題顏色是什麼?你可以使用谷歌給你提供的Material Theme:

  • @android:style/Theme.Material(深色版本)
  • @android:style/Theme.Material.Light(淺色版本)
  • @android:style/Theme.Material.Light.DarkActionBar

當然,也可以使用自定義的主題,先看一下非常普遍的圖片:

image.png

可以通過定製不同的類別的主題顏色,來達到預期的主題效果。

  • colorPrimary 專案主顏色,一般是Titlebar的背景顏色
  • colorPrimaryDark 比主顏色深一點顏色,一般是狀態列顏色
  • textColorPrimary 文字的主顏色
  • windowBackground 視窗背景顏色
  • navigationBarColor 導航欄顏色

通過在styles中配置顏色來定製您的主題,並在AndroidManifest中應用。 開發

[圖片上傳失敗...(image-3f86ab-1513646879600)]

2、BottomNavigationView

主題構建好了,下面就是主要內容架構,我大致分為四個模組:武器簡介、人物簡介、配件簡介和空頭簡介。那麼底下就需要一個tab進行切換,BottomNavigationView便開始登場。從名字就可以看出 「底部導航view」,主要的作用在於給每個模組一個導航定位的功能。

先看一下效果:

bottomNavigationView.gif

  1. menu/下建立選單檔案:

     <menu xmlns:android="http://schemas.android.com/apk/res/android">
         <group android:checkableBehavior="single">
             <item
                 android:id="@+id/bottom_weapon_inc"
                 android:icon="@drawable/about"
                 android:title="@string/weapon_inc" />
             <!--  省略部分程式碼     -->
         </group>
     </menu>
    複製程式碼
  2. XML中進行引用

     <android.support.design.widget.BottomNavigationView
         android:id="@+id/navigation"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         app:itemBackground="@color/colorPrimary"
         app:itemIconTint="@android:color/white"
         app:itemTextColor="@android:color/white"
         app:menu="@menu/bottom_menu"/>
    複製程式碼
  3. 程式碼中設定點選事件

     navigation!!.setOnNavigationItemSelectedListener {}
    複製程式碼

3、DrawerLayout、NavigationView

BottomNavigationView相對的,不得不介紹一下NavigationView,這兩者都是導航View,後者一般需要配合DrawerLayout實現側滑選單效果。

請看效果:

DrawerLayout.gif

XML直接引用

    <android.support.v4.widget.DrawerLayout
            android:id="@+id/dl_main"
            android:layout_width="match_parent"
            android:layout_weight="1"
            android:layout_height="0dp">
            <!-- 主內容 -->
            <FrameLayout
                android:fitsSystemWindows="true"
                android:id="@+id/fl_content"
                android:layout_width="match_parent"
                android:layout_height="match_parent">
    
            </FrameLayout>
            <!-- 側滑選單內容 -->
            <android.support.design.widget.NavigationView
                android:id="@+id/nv_left"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="start"
                app:headerLayout="@layout/nav_header"
                app:menu="@menu/nav_menu"/>
        </android.support.v4.widget.DrawerLayout>
複製程式碼

通過配置layout_gravity的屬性來設定側滑的方向:start:從左側劃出,end從右側劃出。

headerLayout: 設定其頭佈局
menu: 設定選單佈局
複製程式碼

詳細使用請看我之前寫的一篇部落格:高大上的DrawerLayout

4、Toolbar

整體的架構搭建好了,剩下就是開始每個模組的內容了,內容當然少不了標題,那麼就開始介紹一下Toolbar

Toolbar作為早期AndroidActionBar的替代品,定製性和操作性挺高了不少。使用的時候需要設定NoActionBar的主題。

<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"></style>
複製程式碼

5、RecyclerView+SwipeRefreshLayout

專案中列表肯定是少不了的,那麼這就不得不提RecyclerView了,強大之處不用多說,感興趣的話看一下我之前寫的部落格,對其使用有個簡單的介紹:簡單粗暴RecyclerView

那如果想實現側滑刪除和長按拖拽的功能怎麼辦呢?RecyclerView原生就支援這些,只需要繼承ItemTouchHelper.Callback的類,並實現它幾個抽象方法即可。

  1. 建立實現ItemTouchHelper.Callback的類

     internal inner class ItemTouchHelperCallback : ItemTouchHelper.Callback() {
         override fun getMovementFlags(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder): Int {
             val dragFlags = ItemTouchHelper.UP or ItemTouchHelper.DOWN
             val swipeFlags = ItemTouchHelper.START or ItemTouchHelper.END
             return makeMovementFlags(dragFlags, swipeFlags)
         }
    
         override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, target: RecyclerView.ViewHolder): Boolean {
             myAdapter!!.onItemMove(viewHolder.adapterPosition, target.adapterPosition)
             return false
         }
    
         override fun onSwiped(viewHolder: RecyclerView.ViewHolder, direction: Int) {
             myAdapter!!.onItemDismiss(viewHolder.adapterPosition)
         }
     }
    複製程式碼
  2. RecyclerView建立連線

     val mItemTouchHelper = ItemTouchHelper(ItemTouchHelperCallback())
     mItemTouchHelper.attachToRecyclerView(mRecyclerView)
    複製程式碼

實現效果如下:

RecyclerView.gif

6、CardView

列表結構寫好了,裡面內容得優化吧,CardView自帶圓角和陰影效果,讓每個Item看起來就非常的自然,正如其名像卡片一樣,也符合了Material Design特點。

作為ViewGroup包裹子View實現圓角和陰影的效果:

<android.support.v7.widget.CardView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_margin="2dp"
    app:cardCornerRadius="5dp"
    app:cardElevation="5dp">
</android.support.v7.widget.CardView>
複製程式碼

主要由兩個屬性控制:

  • cardCornerRadius:圓角半徑
  • cardElevation:高度(直接影響陰影的大小)

7、CoordinatorLayout+AppBarLayout+Toolbar

列表寫好了,接下來就是滑動的互動,CoordinatorLayout:作為根View或者是一個活多個子View特定的容器,用於協調子View之間滑動的互動,可以說CoordinatorLayout是整個Design庫中最核心的控制元件。

AppBarLayout其實就是LinearLayout,通過layout_scrollFlags來控制滑動的效果。前提是滑動view必須實現NestedScrollingChild的介面,且需要配置behavior,最基本的使用就是:

<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            android:fitsSystemWindows="true"
            android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            app:layout_scrollFlags="scroll|enterAlwaysCollapsed"
            app:popupTheme="@style/Theme.AppCompat.Light" />
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
        <android.support.v7.widget.RecyclerView
            android:id="@+id/recyclerView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:foregroundGravity="center" />
    </android.support.v4.widget.SwipeRefreshLayout>

</android.support.design.widget.CoordinatorLayout>
複製程式碼

有兩個重點:

  • 滑動的view必須實現NestedScrollingChild介面。比如RecyclerViewNestedScrollView.
  • 必須配置behaviorapp:layout_behavior="@string/appbar_scrolling_view_behavior"

來看一下layout_scrollFlags有哪些屬性,為了方便理解,將可以滑動的view簡稱為ScrollView,設定了layout_scrollFlags稱為DependentView

1. scroll

view必須設定該屬性其他的屬性的才會生效,這個是最基本的屬性。

2. scroll|enterAlways

只要ScrollView滑動,滑動事件就會交給設定DependentView,當DependentView滑動結束才會將事件交給ScorllView。也就是下面的效果:

enterAlways.gif

3. scroll|enterAlwaysCollapsed

ScrollView向下滑動時,DependentView先摺疊到最小高度(這裡是0),然後將事件交給ScrollView,當ScrollView滑動結束,DependentView才繼續滑動事件,直至展開,如下圖所示:

enterAlwaysCollapsed.gif

4. scroll|enterAlwaysCollapsed|enterAlways

這邊就展示一下摺疊的效果,我們先設定最小的高度

    <android.support.v7.widget.Toolbar
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:minHeight="50dp"
        app:layout_scrollFlags="scroll|enterAlwaysCollapsed|enterAlways" />
複製程式碼

展示一下效果:

see.gif

5. scroll|exitUntilCollapsed

這個搭配重點在於上拉的時候,DependentView會先摺疊到最小高度,然後事件全部交給ScrollView。那下拉的時候就是當ScrollView滑動結束,才開始DependentView的滑動事件。

exitUntilCollapsed.gif

6. scroll|enterAlways|snap

這個snap就是在上面的基礎上多了一個回彈的效果,當DependentView正在滑動,此時手指離開螢幕時,DependentView會自動移動到離自己較勁的終點或者始點。效果如下:

snap.gif

上面的屬性完全可以像第四種情況疊加使用,至於效果自己嘗試了了才能感覺到它的奧妙之處。

8、轉場動畫

互動有了,現在看是新增點選跳轉效果了。我們們之前跳轉動畫都是在startActivity之後呼叫overridePendingTransition方法,傳入進入和退出的動畫實現跳轉動畫。Android 5.0提供了強大的轉場動畫,給每個item賦予了生命,跳轉時,彷彿每塊佈局都參與了這次搬遷大運動。

使用時,需在setContentView()之前加上

window.requestFeature(Window.FEATURE_CONTENT_TRANSITIONS)
複製程式碼

跳轉時候這樣寫:

startActivity(intent, ActivityOptions.makeSceneTransitionAnimation(activity).toBundle())
複製程式碼

跳轉的介面設定轉場動畫或者出場動畫:

    window.enterTransition = Explode()
    window.exitTransition = Slide()
複製程式碼

為了看出效果我設定了2s的延遲:

Transition.gif

9、Toast、SnackBar和AlertDialog

基本的介面寫完了,剩下的就是一些邏輯上的操作啦,比如「提示」。那麼Android提示分為三種:

  • 友好的Toast(比如網路失敗)
  • 擁有附加行為的提示SnackBar(比如誤刪資訊回撤)
  • 強制讓使用者做出選擇的AlertDialg(比如未登入)

那麼這三種的效果是什麼呢?

TSA.gif

大概先講這些,有時間再進行後續補充。

Material Design 在「口袋」中的應用

其實在我們們的「口袋貴金屬」專案中也到找到很多MD的元素。

首先是點選的水波紋效果:

ripple.gif

其次是交易圈的滑動互動:

circle.gif

還有就是本人在「口袋」接手的第二個需求,「個人中心」。看一下效果:

personal.gif

嚴格按照Material Design風格進行開發,相信一定能開發出非常漂亮的APP

相關文章