Android 5.0 新特性



Material Design

      
      
      
              

Material Design簡介

Material Design是谷歌新的設計語言,谷歌希望寄由此來統一各種平台上的用戶體驗,Material Design的特點是干凈的排版和簡單的布局,以此來突出內容

Material Design對排版、材質、配色、光效、間距、文字大小、交互方式、動畫軌跡都做出了建議,以幫助設計者設計出符合Material Design風格的應用。

Material Design設計語言鼓勵大家使用充滿活力的鮮艷色彩,並在同一界面建議使用三種色調,並保障有一個強色調,強色一般處於處於視圖最底層,例如狀態欄或者actionbar。通過強色調形成鮮明的對比,更容易突出內容的重要性。對於文字色彩的取值,Material Design建議在淺色背景上采用黑色,在深色背景上采用白色。重要信息和標題采用87%透明度,次要文字采用54%透明度,而更次要的說明文字可以采用26%的透明度。對於想特別突出或者可點擊的文字,建議使用強色調。不同層級的視圖,可以通過陰影來凸顯。對於帶有操作且內容突出的區域,可以使用cardview進行隔離,對於內容不太重要或者操作比較單一的區域,可以使用分割線進行隔離。

更多詳情請見Material Design文檔:

中文版網站 http://design.1sters.com/

英文版 http://www.google.com/design/spec/material-design/introduction.html

Material Design使用

作為我們開發者,最關心的還是如何在項目中使用Material Design風格:

  1. 設置應用的 targetSdkVersion 為21
  2. 在values目錄下的style資源文件中創建一個style,讓其繼承自 android:Theme.Material
  3. 在AndroidManifest中指定應用的主題或者Activity的主題為我們設定的樣式

谷歌官方我們提供了三種配色風格的Material Design樣式:

  1. 黑色主題 Theme.Material
  2. 明亮主題 Theme.Material.Light
  3. 明亮主題黑色ActionBar Theme.Material.Light.DarkActionBar

我們也可以繼承系統提供的Material Design樣式,進行配色修改:

Mou icon

  1. android:colorPrimaryDark 應用的主要暗色調,statusBarColor默認使用該顏色
  2. android:statusBarColor 狀態欄顏色,默認使用colorPrimaryDark
  3. android:colorPrimary 應用的主要色調,actionBar默認使用該顏色
  4. android:windowBackground 窗口背景顏色
  5. android:navigationBarColor 底部欄顏色
  6. android:colorForeground 應用的前景色,ListView的分割線,switch滑動區默認使用該顏色
  7. android:colorBackground 應用的背景色,popMenu的背景默認使用該顏色
  8. android:colorAccent 一般控件的選中效果默認采用該顏色
  9. android:colorControlNormal 控件的默認色調 
  10. android:colorControlHighlight 控件按壓時的色調
  11. android:colorControlActivated 控件選中時的顏色,默認使用colorAccent
  12. android:colorButtonNormal 默認按鈕的背景顏色
  13. android:textColor Button,textView的文字顏色
  14. android:textColorPrimaryDisableOnly RadioButton checkbox等控件的文字
  15. android:textColorPrimary 應用的主要文字顏色,actionBar的標題文字默認使用該顏色

主題不僅可以對ApplicationActivity使用,也可以對某一個控件單使用,或者是在xml布局中給一個根節點控件設置android:theme屬性,來修改它和它所有子控件的主題。 如果我們要對特定控件實例做自定義修改,建議通過控件自身的API進行設置修改。

Material Design兼容性

Material Design主題只有在API級別為21以上才可使用,在v7支持庫中提供了部分控件的Material Design主題樣式,如果想使應用在android的所有版本上都能統一風格,我們可以對控件效果做自定義或者使用一些第三方的兼容包。目前最有效的做法是針對21版本創建value-21資源目錄,使用Material Design風格主題,在其他版本使用v7的Theme.AppCompat.Light風格主題。


陰影和裁剪

      
      
      
              

View的z屬性

Material Design建議為了凸顯布局的層次,建議使用陰影效果,並且Android L為了簡化大家的工作,對View進行了擴展,能使大家非常方便的創建陰影效果:

陰影

給View添加了一個新的屬性:Z 屬性,用於描述視圖距離它父視圖的高度:

在5.0之前,我們的視圖都是二維的,只有x軸和y軸,現在,android新增了z軸。x軸和y軸描述了一個view的大小和位置,而z軸描述了view在父視圖上抬起的視覺,體現效果就是陰影。下圖的兩個view的z屬性分別為2dp和8dp的視覺效果:

z軸

View的Z屬性可以通過elevation和translationZ進行修改。

z = elevation+translationZ

在5.0之前,我們如果想給view添加陰影效果,以體現其層次感,通常的做法是給view設置一個帶陰影的背景圖片,現在,我們只需要簡單的修改view的Z屬性,就能讓其具備陰影的層次感。

Z屬性會擴大view的顯示區域,如果它的大小大於或等於父視圖的大小,那么它的陰影效果就無法顯示了,view並不會因為z屬性而把自身縮小騰出空間顯示陰影

Z屬性不僅影響着view的陰影效果,還影響着view的繪制順序,在同一個父view內部,Z屬性越小,繪制的時機就越早。也就是優先被繪制,而z屬性越大,則繪制時間越晚,后繪制的將會遮蓋住先繪制的,只有Z屬性相同,才按照添加的順序繪制。

View的輪廓

在Android的世界里,所有的View都是矩形的,雖然可以給View設置背景圓形的圖片,即可在界面顯示出圓形的內容,但是View的大小實際上仍然是矩形,並且設置的圖片也是實際上也是矩形,只是圓形意外的區域為透明色。

如果系統根據View的大小來為我們生成對應的陰影,有時候就會出現很奇怪的效果。

為了解決該類問題,View增加了一個新的描述來指明內容顯示的形狀,這就是輪廓。通過shape設置的背景,View會自動根據shape的形狀進行輪廓判定,通過color設置的背景,View默認其輪廓和View的大小一樣。但是通過圖片進行背景設置,View則無法獲知輪廓的形狀,這個時候就需要我們程序員顯示的指定。

在xml布局中,可以通過android:outlineProvider來指定輪廓的判定方式:

  1. none 即使設置了Z屬性,也不會顯示陰影
  2. background 會按照背景來設置陰影形狀
  3. bounds 會按照View的大小來描繪陰影
  4. paddedBounds 和bounds類似,不過陰影會稍微向右偏移一點

在代碼中,我們可以通過setOutlineProvider來指定一個View的輪廓:

ViewOutlineProvider viewOutlineProvider = new ViewOutlineProvider() { public void getOutline(View view, Outline outline) { // 可以指定圓形,矩形,圓角矩形,path outline.setOval(0, 0, view.getWidth(), view.getHeight()); } }; View.setOutlineProvider(viewOutlineProvider ); 

注意:如果采用圖片作為背景,即使在xml布局中指定android:outlineProvider為background也不會顯示陰影,只有通過代碼中指定輪廓來顯示。

View的剪裁

給View指定輪廓,可以決定陰影的顯示形狀,如果給View指定一個小於自身大小的輪廓,正常情況下陰影會被View遮住,這個時候View的顯示內容並沒有因為輪廓的縮小而縮小。

如果想根據輪廓來縮小一個View,則可以通過剪裁。如果一個View指定了輪廓,調用setClipToOutline方法,就可以根據輪廓來剪裁一個View。想要剪裁輪廓,必須要給View先指定輪廓,並且輪廓是可以被剪裁的,目前只有圓形,矩形,圓角矩形支持剪裁,可以通過outline.canClip()來判斷一個輪廓是否支持剪裁。

Path剪裁不會改變View的大小,但是如果Path的范圍比View要的bounds要小,則剪裁后會改變View的位置,位置偏移和Z屬性有關,這可能是一個BUG,view的設計者可能在繪制陰影時根據輪廓偏移了畫布,而在繪制完后忘記把畫布還原了。

剪裁不會改變View的測量大小和布局大小,也不會改變View的觸摸區域,剪裁只是在onDraw的時候對畫布做了剪裁處理,剪裁也不同於scale,scale是調整畫布matrix的縮放屬性,調整后,View仍然能完整顯示,而剪裁是縮小畫布的剪裁區域,剪裁后我們只能看到View的一部分。

試圖給View一個比較大的輪廓進行剪裁也是不成功的,實驗證明剪裁后的View只能比原有體積小,擴大輪廓只會擴大輪廓的繪制區域

剪裁是一個非常消耗資源的操作,我們不應該用此來做動畫效果,如果要實現這樣的動畫,可以使用Reveal Effect


圖片和顏色

      
      
      
              

tint屬性

tint屬性是一個顏色值,可以對圖片做顏色渲染,我們可以給view的背景設置tint色值,給ImageView的圖片設置tint色值,也可以給任意Drawable或者NinePatchDrawable設置tint色值。

在應用的主題中也可以通過設置 android:tint 來給主題設置統一的顏色渲染。

tint的渲染模式有總共有16種,xml文件中可以使用6種,代碼中我們可以設置16種,渲染模式決定了渲染顏色和原圖顏色的取舍和合成規則:

  1. PorterDuff.Mode.CLEAR 所繪制不會提交到畫布上。
  2. PorterDuff.Mode.SRC 顯示上層繪制圖片
  3. PorterDuff.Mode.DST 顯示下層繪制圖片
  4. PorterDuff.Mode.SRC_OVER 正常繪制顯示,上下層繪制疊蓋。
  5. PorterDuff.Mode.DST_OVER 上下層都顯示。下層居上顯示。
  6. PorterDuff.Mode.SRC_IN 取兩層繪制交集。顯示上層。
  7. PorterDuff.Mode.DST_IN 取兩層繪制交集。顯示下層。
  8. PorterDuff.Mode.SRC_OUT 取上層繪制非交集部分。
  9. PorterDuff.Mode.DST_OUT 取下層繪制非交集部分。
  10. PorterDuff.Mode.SRC_ATOP 取下層非交集部分與上層交集部分
  11. PorterDuff.Mode.DST_ATOP 取上層非交集部分與下層交集部分
  12. PorterDuff.Mode.XOR 取兩層繪制非交集。兩層繪制非交集。
  13. PorterDuff.Mode.DARKEN 上下層都顯示。變暗
  14. PorterDuff.Mode.LIGHTEN 上下層都顯示。變亮
  15. PorterDuff.Mode.MULTIPLY 取兩層繪制交集
  16. PorterDuff.Mode.SCREEN 上下層都顯示。

通過tint屬性處理后的圖片會和原圖顯示出不一樣的顏色,我們可以通過這種方式利用一張圖片做出圖片選擇器的效果,讓控件在按壓狀態下顯示另外一種顏色:

通過給圖片設置tint色生成另外一種圖片
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ring"
android:tintMode="multiply"
android:tint="#5677fc" />
利用新的圖片生成圖片選擇器
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/tint_bitmap" android:state_pressed="true"/>
<item android:drawable="@drawable/ring" />
</selector>

Palette調色版

Palette調色板,可以很方便的讓我們從圖片中提取顏色。並且可以指定提取某種類型的顏色。

  1. Vibrant 鮮艷的
  2. Vibrant dark鮮艷的暗色
  3. Vibrant light鮮艷的亮色
  4. Muted 柔和的
  5. Muted dark柔和的暗色
  6. Muted light柔和的亮色

對圖片取色是一個比較消耗性能的操作,其內部會對圖片的像素值進來遍歷以分析對比,所以我們要在異步線程中去完成。

如果操作本來就屬於后台線程,可以使用: Palette p = Palette.generate(Bitmap bitmap); 如果在主線程中,我們可以使用異步的方式: Palette.generateAsync(bitmap, new Palette.PaletteAsyncListener() { public void onGenerated(Palette palette) {  } }); 

當操作完成后或者異步回調后,我們就可以使用以下方式來獲取對應的色值了,並且可以在沒有獲取到的情況下之指定默認值:

p.getVibrantColor(int defaultColor); p.getDarkVibrantColor(int defaultColor); p.getLightVibrantColor(int defaultColor); p.getMutedColor(int defaultColor); p.getDarkMutedColor(int defaultColor); p.getLightMutedColor(int defaultColor); 

在使用palette之前,bitmap提供獲取指定位置的像素值:

bitmap.getPixel(x,y) 

但是該方式只能獲取某一點的像素值,palette是對整個bitmap的所有像素值進行分析,並選出幾個像素占比比較多的像素值,這樣選擇出來的色值更符合圖片的整體色值。

vector矢量圖

矢量圖也稱為面向對象的圖像或繪圖圖像,是計算機圖形學中用點、直線或者多邊形等基於數學方程的幾何圖元表示的圖像。矢量圖形最大的優點是無論放大、縮小或旋轉等不會失真;最大的缺點是難以表現色彩層次豐富、逼真的圖像效果。

Android L開始支持矢量圖,我們可以用它來處理一些圖形簡單的icon,方便我們的適配。

Android L中對矢量圖的支持是通過xml文件構建,通過矢量圖的path描述來生成一個矢量圖,對應的java對象為VectorDrawable。

下面是官方文檔提供的一個矢量圖,利用改文件,我們可以創建一個隨意放大縮小都不會失真的心形。

<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="300dp" android:width="300dp" android:viewportHeight="40" android:viewportWidth="40"> <path android:fillColor="#ff00ff" android:pathData="M20.5,9.5 c-1.955,0,-3.83,1.268,-4.5,3 c-0.67,-1.732,-2.547,-3,-4.5,-3 C8.957,9.5,7,11.432,7,14 c0,3.53,3.793,6.257,9,11.5 c5.207,-5.242,9,-7.97,9,-11.5 C25,11.432,23.043,9.5,20.5,9.5z"/> </vector> 

矢量圖的pathData數據就是用來描述矢量圖的數學公式,其含義如下表:

命令類型 使用描述 代表含義 舉例說明
移動指令 M x,y M移動絕對位置 M 100,240
移動指令 m x,y m移動相對於上一個點 m 100,240
繪制 L 或 l 從當前點繪制直線到指定點 L 100,100
繪制 H 或 h 水平直線 h 100
繪制 V 或 v 垂直直線 v 100
繪制 C 或 c 三次方程式貝塞爾曲線 C 100,200 200,400 300,200
繪制 Q 或 q 二次方程式貝塞爾曲線 Q 100,200 300,200
繪制 S 或 s 平滑三次方程式貝塞爾曲線 S 100,200 200,400 300,200
繪制 T 或 t 平滑二次方程式貝塞爾曲線 T 100,200 300,200
繪制 A 或 a 橢圓 A 5,5 0 0 1 10,10
關閉指令 Z 或 z 將圖形的首、尾點用直線連接 Z
填充 F0 EvenOdd 填充規則
填充 F1 Nonzero 填充規則

通過path命令來進行簡單的圖形還是可行的,但是復雜的圖形我們就需要借助工具來生成了,比如使用 Expression Design,就可以直接粘貼來自其它軟件的矢量圖形,然后選擇導出,導出時做如后選擇:文件->導出->導出屬性->格式->XAML Silverlight 畫布,即可得到XAML格式的矢量圖形,也就是Path。

更多矢量圖學習可參考:http://www.w3.org/TR/SVG11/paths.html#PathData 我們可以訪問http://editor.method.ac 在線制作矢量圖並導出path。


新增Widget

     
     
     
             

RecyclerView

RecyclerView是ListView的升級版,它具備了更好的性能,且更容易使用。和ListView一樣,RecyclerView是用來顯示大量數據的容器,並通過復用有限數量的View,來提高滾動時的性能。當你的視圖上的元素經常動態的且有規律的改變時候,可以使用RecyclerView控件。

與ListView不同的是RecyclerView不再負責布局,只專注於復用機制,布局交由LayoutManager來管理。 RecyclerView仍然通過Adapter來獲取需要顯示的對象。

Mou icon

要使用RecyclerView組件,創建Adapter不再繼承自BaseAdapter,而是應該繼承自RecyclerView.Adapter類,並且最好指定一個繼承自RecyclerView.ViewHolder的范型,Adapter不再要求你返回一個View,而是一個ViewHolder。

繼承自Adapter后,需要實現3個抽象方法:

// 當RecyclerView需要一個ViewHolder時會回調該方法,如果有可復用的View則該方法不會得倒回調 public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i); // 當一個View需要出現在屏幕上時,該方法會被回調,你需要在該方法中根據數據來更改視圖 public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int i); // 用於告訴RecyclerView有多個視圖需要顯示 public int getItemCount();

新的Adapter和原有的Adapter並沒有太多的差別,只是不再需要我們寫復用判斷的邏輯,因為復用邏輯其實都是相似的,它已經有了自身的實現。和原有的Adapter一樣,仍然可以通過notifyDataSetChanged來刷新UI,通過getItemViewType來獲取對應位置的類型,但是它不再需要你指定有多少類型了,因為該方法已經能夠判斷出有多少類型。新增的onViewRecycled方法可以讓使用者監聽View被移除屏幕的時機,並且還提供了一個AdapterDataObserver的觀察者,對外提供數據改變時的回調。

ViewHolder是對所有的單個item的封裝,不僅包含了item需要顯示的View,並且還包含和item相關的其它數據,例如:當前的position、之前的position、即將顯示的position、被回收的次數、View的類型、是否處於顯示中等信息。創建一個ViewHolder需要傳遞一個View對象,這個View就是該holder的顯示視圖,該View中通常會包含一些子視圖,我們最好把這些子視圖都記錄在holder中,便於復用時設置不同的數據。

RecyclerView不再對布局進行管理,而是通過LayoutManager管理布局,我們可以通過繼承自LayoutManager來實現特殊的布局,系統提供了三種常用的布局管理器:

  1. LinearLayoutManager 線性布局
  2. GridLayoutManager 九宮格布局
  3. StaggeredGridLayoutManager 瀑布流布局

並且每一種都可以設置橫行和縱向的布局,可惜的均不能添加header,如果要添加header,我們可以在Adapter中使用不同的類型來達到該效果。

RecyclerView默認提供了item的增加和刪除的動畫效果,如果我們使用自定義的動畫,需要繼承繼承RecyclerView.ItemAnimator類,通過RecyclerView.setItemAnimator()方法來設置我們自定義的動畫。

CardView

在實現扁平化的UI處理上,通常離不開陰影和圓角,我們通常是讓美工提供一個帶有陰影和圓角效果的背景圖片,現在我們有了更好的實現方式,那就是CardView。

CardView實際是一個FrameLayout類的子類,它為視圖提供卡片樣式,並保持在不同平台上擁有統一的風格。CardView組件可以設定陰影和圓角。

我們可以使用cardElevation屬性在xml布局中設置陰影效果,在代碼中可以通過setCardElevation達到同樣的效果。陰影的設置和Android L中的Z屬性類似。

設置圓角也相當容易,在xml中通過cardCornerRadius來設置,在代碼中則使用setRadius,圓角的設置和Android L中的剪裁很相似。

如果我們想設置cardview的背景,請注意使用carBackgroundColor方法,setBackgroundColor也許會影響我們的圓角效果

ToolBar

Toolbar是android L引入的一個新控件,用於取代ActionBar,它提供了ActionBar類似的功能,但是更靈活。不像ActionBar那么固定,Toolbar更像是一般的View元素,可以被放置在view樹體系的任意位置,可以應用動畫,可以跟着ScrollView滾動,可以與布局中的其他View交互。當然,你還可以用Toolbar替換掉ActionBar,只需調用Activity.setActionBar()。

為了兼容更多的設備一般我們都是通過AppCompat中的android.support.v7.widget.Toolbar來使用Toolbar。

有兩種使用Toolbar的方式:

  1. 將Toolbar當作actionbar來使用。這種情況一般發生在你想利用actionbar現有的一些功能(比如能夠顯示菜單中的操作項,響應菜單點擊事件,使用ActionBarDrawerToggle等),但是又想獲得比actionbar更多的控制權限。
  2. 將Toolbar當作一個獨立的控件來使用,這種方式又名Standalone。

如果你要將Toolbar當作actionbar來使用,你首先要去掉actionbar,最簡單的方法是使用Theme.AppCompat.NoActionBar主題。或者是設置主題的屬性android:windowNoTitle為true。然后在Activity的onCreate中調用setSupportActionBar(toolbar),原本應該出現在ActionBar上的menu會自動出現在actionbar上。

Toolbar的高度、寬度、背景顏色等等一切View的屬性完全取決於你,這都是因為Toolbar本質上只是個ViewGroup。將Toolbar當作一個獨立的控件來使用是不需要去掉actionbar的(兩者可以共存),可以使用任意主題。但是在這種情況下,menu菜單並不會自動的顯示在Toolbar上,Toolbar也不會響應菜單的回調函數,如果你想讓menu菜單項顯示在Toolbar上,必須手動inflate menu。

toolbar.setOnMenuItemClickListener(new Toolbar.OnMenuItemClickListener() { @Override public boolean onMenuItemClick(MenuItem item) { // 處理menu事件 return true; } }); // 創建一個menu添加到toolbar上 toolbar.inflateMenu(R.menu.your_toolbar_menu);

兼容性

     
     
     
             

雖然Material Design新增了許多新特性,但是並不是所有新內容對對下保持了兼容。

使用v7包

v7 support libraries r21 及更高版本包含了以下Material Design特性:

  1. 使用Theme.AppCompat主題包含調色板主體屬性,可以對應用的主題做統一的配色,但是不包括狀態欄和底部操作欄
  2. RecyclerView和CardView被獨立出來,只要引入jar包,即可適配7以上的所有版本。
  3. Palette類用於從圖片提取主色調

系統組件

Theme.AppCompat主題中提供了這些組件的Material Design style:

  1. EditText
  2. Spinner
  3. CheckBox
  4. RadioButton
  5. SwitchCompat
  6. CheckedTextView
  7. Color Palette

創建多個value和layout

針對Android L我們可以創建value-v21指定Material Design主題,而在其他value中指定Theme.AppCompat。layout布局也可以采用該方式,在Android L中使用系統控件,在低版本中使用我們自定義的控件活着第三方包來達到該效果。

注意版本檢查

以下特性只在Android 5.0 (API level 21) 及以上版本中可用:

  1. 轉場動畫
  2. 觸摸反饋
  3. 圓形展示動畫
  4. 路徑動畫
  5. 矢量圖
  6. tint染色

所以在代碼中遇上使用這些api的地方需要進行版本判斷:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
// 使用新特性
} else {
// 用其他替代方式
}

第三方支持庫

RippleDrawable

提供觸摸反饋特效,即5.0的button按壓下的水波紋效果。

  1. https://github.com/03uk/RippleDrawable 
  2. https://github.com/siriscac/RippleView 
  3. https://github.com/balysv/material-ripple 
狀態動畫

https://github.com/NghiaTranUIT/Responsive-Interaction-Control 

Material Design風格的對話框

https://github.com/lewisjdeane/L-Dialogs 

Material Design風格兼容包

提供了不少控件特效 https://github.com/navasmdc/MaterialDesignLibrary

SystemBarTint

支持修改狀態欄和底部操作欄 https://github.com/jgilfelt/SystemBarTint 







免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM