Material Design入門(下)

    除了Google官方提供的組件,Material Design另一個非常重要的特性是它的視圖效果,這些效果和官方的組件一起,爲安卓app的交互提供了更好的素材

1.Elevation:高度

      先介紹從Android L(5.0)以後谷歌引入的一個非常重要的概念:高度和陰影,就是將z軸引入視圖的展現,讓界面不再是呆板的二維視圖,更真實和立體,具有視覺上的高度層次和陰影投射。

    
    這裏的高度就是elevation,而實際上視圖高度Z=elevation+translationZ。這裏先說高度,elevation可以在佈局文件或代碼中指定,用dp表示,一般來說其值越大陰影越明顯越柔和,但並不會改變視圖本身大小。

2.輪廓和剪裁
     輪廓(Outlines)代表了圖形對象的外邊緣線,如果是一個以color作爲背景的View,輪廓也就是該View的大小,僅僅修改elevation就可以獲取陰影效果。但如果以一張圖片作爲背景,這時候光定義了elevation是不夠的,需要通過代碼指定輪廓的形狀和邊界。
ImageView iv = findViewById(R.id.iv);
        ViewOutlineProvider provider=new ViewOutlineProvider() {
            @Override
            public void getOutline(View view, Outline outline) {
                outline.setOval(0, 0, view.getWidth(), view.getHeight());
            }
        };
        iv.setOutlineProvider(provider);
       ViewOutlineProvider是官方提供的一個抽象類,重寫其中的方法可以輕鬆的改變基本的輪廓顯示。同樣在xml佈局中,可以通過android:outlineProvider來指定輪廓的判定方式。有四種:bounds,background,none,paddedBounds,系統默認爲background。
      如果想根據輪廓來縮小一個View,則可以開啓剪裁功能:view.setClipToOutline(true).要注意剪裁是一個很耗資源的操作,不應該用此做動畫效果。下圖左邊是正常的圖片,右邊是輪廓的長寬分別是原View的一半進行裁剪後的圖片:




3.Palette:調色版
    Palette是用於谷歌提供的一個可以用於從Bitmap中提取主色調的工具類,可以讓UI界面更柔和,使用起來也非常簡單:首先將網絡圖片或者本地圖片轉換爲Bitmap對象,然後調用Palette的異步回調,提供了六種可提取的顏色:Vibrant(有活力的)、LightVibrant(有活力的亮色)、DarkVibrant(有活力的暗色)、Muted(柔和的)、LightMuted(柔和的亮色)、DarkMuted(柔和的暗色)。下圖從左至右依次展示了從示例圖片中提取的六種色調。


4.Vector:矢量圖

    谷歌5.0之後推出了對矢量圖的支持(Vector),借鑑了Web前端強大的自定義圖形的特性。好處是很明顯的:可以自適配、可代替不是十分複雜的PNG圖片來減小體積可將導出的標準SVG圖像直接轉化爲PNG圖像、除了靜態圖片還可以實現一些複雜的動畫。

(1)實現靜態圖片:

        通過查看官方文檔,其實就是一個xml文件,根元素是vector

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="300dp"
    android:height="300dp"
    android:viewportHeight="40"
    android:viewportWidth="40" >
    
    <path
        android:fillColor="#ff0040"
        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 >
    上述代碼定義的是一個桃心,幾個標籤的含義: android:width \ android:height:圖片的寬高、android:viewportWidth\ android:viewportHeight:圖片被劃分的比例大小,比如這裏就是將300dp劃分爲40份,後面path標籤中的座標就全部使用這裏劃分後的座標系統。

      重點看path中的pathData標籤,用SVG語法定義了畫筆該怎麼畫出目標圖形,而不用自定義View。支持的指令如下:


    tips:座標軸以(0,0)爲中心,X軸水平向右,Y軸水平向下。所有指令大小寫都可以,但是注意大寫會參照全局座標系,小寫會參照父容器座標系。指令和數據之間的空格可以省略。各種各樣的SVG工具也可以幫我們導出圖形,大概知道SVG語法含義即可。

5.全新的動畫

   5.1 矢量動畫
     上面介紹了矢量圖,所以這裏先介紹VectorAnim:矢量動畫。谷歌提供了一個AnimatedVectorDrawable去爲VectorDrawable賦予動畫特性,也就是創建一個矢量資源的動畫。在xml中使用的簡單步驟如下:
1.在res/drawable下創建一個根節點爲<animated-vector>的xml。它相當於一個橋樑,指定要顯示動畫的圖片和一個具體的動畫。佈局文件中要顯示效果的控件就以它爲background.
<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/vector_triangle" >

    <target
        android:name="v"
        android:animation="@anim/path_morph" />

    <!--android:name="v"  指定要驅動的vetordrawable內的group和path名稱 -->
    <!--android:animation="@anim/path_morph"  指定用哪個動畫驅動該vectordrawable -->

</animated-vector >
2.在res/drawable下創建<vector>的矢量資源
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="64dp"
    android:height="64dp"
    android:viewportHeight="600"
    android:viewportWidth="600" >

    <path
        android:name="v"
        android:fillColor="#1a65cf"
        android:pathData="M300,70 l 0,-70 70,70 0,0 -70,70z" />

</vector >
3.在res/anim下創建<objectAnimator>動畫資源,也就是一個或多個對象動畫器。
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" >

    <objectAnimator
        android:duration="5000"
        android:propertyName="pathData"
        android:valueFrom="M300,70 l 0,-70 70,70 0,0 -70,70z"
        android:valueTo="M300,70 l 0,-70 70,0 0,140 -70,0 z"
        android:valueType="pathType" >

    </objectAnimator >
</set >
4.佈局文件中使用該drawable的控件,點擊後開啓動畫
final View view = findViewById(R.id.view);
        view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Drawable background = view.getBackground();
                if (background instanceof Animatable) {
                    ((Animatable) background).start();
                }
            }
        });
    5.2 觸摸反饋
    Material Design加入了觸摸反饋動畫,讓控件點擊後交互更直觀。最典型的就是水波紋動畫,即控件點擊後從點擊位置產生類似水波紋的擴散效果。安卓5.0之後Button默認帶有水波紋效果。設置水波紋背景效果有兩種:

android:background="?android:attr/selectableItemBackground"     波紋有邊界

android:background="?android:attr/selectableItemBackgroundBorderless"    波紋超出邊界
效果圖:


     5.3 揭蓋動畫
      不知道爲什麼會翻譯成這個名字,大概是給人一種呈現(Reveal)的效果吧。官方提供了一個工具類ViewAnimationUtils,這個工具類非常簡單,裏面只有一個靜態方法,返回值是一個Animator對象,爲其設置時間就可以開始動畫了。從名字就能看出實現的效果是以圓形展示出來的動畫。
public static Animator createCircularReveal(View view,
            int centerX,  int centerY, float startRadius, float endRadius) {
        return new RevealAnimator(view, centerX, centerY, startRadius, endRadius);
    }
五個參數,view:要操作的控件;centerX、centerY:動畫開始的中心點座標,相對view自身的;startRadius:開始半徑;endRadius:結束時的半徑。

     5.4 過渡動畫
      新增了幾種Activity的過場動畫。Activity的Transition有兩種類型:Enter和Exit


6.RecyclerView

        RecyclerView應該算是安卓5.0中引入的最重要的控件了,和ListView一樣,它也是列表容器,同樣要用適配器綁定數據源。谷歌設計此控件是爲了能替代ListView,它和ListView相比有以下幾個特點:
(1)都要使用到適配器。ListView一般我們定義一個適配器,繼承自BaseAdapter。包括裏面的convertView和ViewHolder都是谷歌建議我們的一種寫法,可以提供條目重用節省內存。RecyclerView同樣需要適配器,繼承自其內部的一個抽象類Adapter,我們只需要實現onCreateViewHolder和onBindViewHolder這兩個方法就可以。
(2)RecyclerView需要設置佈局管理器,否則不會顯示數據。因爲ListView只提供了縱向列表的展現,而RecyclerView中引入了LayoutManager(佈局管理器)的概念。可以根據列表所要展現的特性自己擴展該抽象類。API提供了三種佈局管理器,一般就可以滿足需求
1. LinearLayoutManager 線性佈局,效果和普通的ListView一樣

2.  GridLayoutManager 網格佈局
最常見的構造方法是縱向的網格佈局,第二個參數指定九宮格的列數:

        還有一種構造方法是可以指定爲橫向的網格佈局,這時效果就類似於橫向滑動的ViewPager,可以指定每頁的行數。這種效果比較少見。

 3.  StaggeredGridLayoutManager  瀑布流佈局
可以根據指定的方向(橫,豎)系統自動切換參數爲行數或者列數

(3)RecyclerView不再像ListView一樣自帶條目間的分隔線,需要自己實現ItemDecoration這個抽象類。第三方有很多各種各樣的相關資料,現在對於豎直排列的佈局,谷歌官方也提供了一個DividerItemDecoration,已經可以滿足要求了,分隔線設計的過於複雜沒有什麼意義。
(4)列表的增刪移改具有了動畫效果,官方內置默認使用的動畫實現是DefaultItemAnimator,另外提供了一個SimpleItemAnimator,同樣你也可以自己實現RecyclerView內部的抽象類ItemAnimator來獲取你要的效果。並且Adapter中提供了很多局部刷新的方法:notifyItemChanged、notifyItemInserted、notifyItemMoved、notifyItemRemoved,並且都帶很自然的動畫效果。不一定非使用notifyDataSetChanged來全局刷新。下例爲添加和刪除條目時的動畫效果:

(5)不同於ListView,RecyclerView沒有提供列表點擊的回調事件setOnItemClickListener,可以在自定義的Adapter內部通過接口回調實現。不過我認爲ViewHolder裏面的成員變量itemView本身就代表了點擊,我們可以將點擊事件放到Adapter裏面實現,不一定非要在組件上取得回調。

        以上,RecyclerView新引進了很多功能,但又最大化的提供瞭解耦。它自身只負責條目的回收和複用,其餘的佈局排列、UI實現、動畫效果則全部交出去完成。
          需要注意的是:在創建Adapter時,onCreateViewHolder方法中如果用LayoutInflater加載佈局,這裏的父容器不能再像ListView一樣置爲null。否則條目中的match_parent屬性等並不會真正的和父容器(RecyclerView定義的佈局)參數一致,而會根據當前內容自適應寬度。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章