Android5.0新特性——陰影和剪裁(shadow)


陰影和剪裁

View的z屬性

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

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

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

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


免責聲明!

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



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