陰影和剪裁
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來指定輪廓的判定方式:
none即使設置了Z屬性,也不會顯示陰影background會按照背景來設置陰影形狀bounds會按照View的大小來描繪陰影paddedBounds和bounds類似,不過陰影會稍微向右偏移一點
在代碼中,我們可以通過setOutlineProvider來指定一個View的輪廓:
|
注意:如果采用圖片作為背景,即使在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
