天天看點

Android動畫的了解

在我們開始講Android動畫這個知識點之前,我們了解下相應的基礎知識點。

一般用Shape定義的XML檔案是存放在Drawable目錄下,廣泛應用于在Button、TextView、EditText等各種基本控件中,來實作不同背景、顔色、邊框。

使用Shape可以自定義形狀,可以定義下面四種類型的形狀,通過android:shape屬性指定:

rectangle:矩形,預設的形狀

oval:橢圓形,可以畫正圓

line:線形,可以畫實線和虛線

ring:環形,可以話進度條之類

rectange

solid: 設定形狀填充的顔色,隻有android:color一個屬性 android:color 填充的顔色 padding: 設定内容與形狀邊界的内間距,可分别設定左右上下的距離 android:left 左内間距 android:right 右内間距 android:top 上内間距 android:bottom 下内間距 gradient: 設定形狀的漸變顔色,可以是線性漸變、輻射漸變、掃描性漸變 android:type 漸變的類型linear 線性漸變,預設的漸變類型radial 放射漸變,設定該項時,android:gradientRadius也必須設定sweep 掃描性漸變 android:startColor 漸變開始的顔色 android:endColor 漸變結束的顔色 android:centerColor 漸變中間的顔色 android:angle 漸變的角度,線性漸變時才有效,必須是45的倍數,0表示從左到右,90表示從下到上 android:centerX 漸變中心的相對X坐标,放射漸變時才有效,在0.0到1.0之間,預設為0.5,表示在正中間 android:centerY 漸變中心的相對X坐标,放射漸變時才有效,在0.0到1.0之間,預設為0.5,表示在正中間 android:gradientRadius 漸變的半徑,隻有漸變類型為radial時才使用 android:useLevel 如果為true,則可在LevelListDrawable中使用 corners: 設定圓角,隻适用于rectangle類型,可分别設定四個角不同半徑的圓角,當設定的圓角半徑很大時,比如200dp,就可變成弧形邊了 android:radius 圓角半徑,會被下面每個特定的圓角屬性重寫 android:topLeftRadius 左上角的半徑 android:topRightRadius 右上角的半徑 android:bottomLeftRadius 左下角的半徑 android:bottomRightRadius 右下角的半徑 stroke: 設定描邊,可描成實線或虛線。 android:color 描邊的顔色 android:width 描邊的寬度 android:dashWidth 設定虛線時的橫線長度 android:dashGap 設定虛線時的橫線之間的距離

oval

它也有solid、padding、stroke、gradient、size幾個特性,size是用來設定形狀大小的,如下: size: 設定形狀預設的大小,可設定寬度和高度 android:width 寬度 android:height 高度

line

畫線時,有幾點特性必須要知道的: 隻能畫水準線,畫不了豎線; 線的高度是通過stroke的android:width屬性設定的; size的android:height屬性定義的是整個形狀區域的高度; size的height必須大于stroke的width,否則,線無法顯示; 線在整個形狀區域中是居中顯示的; 線左右兩邊會留有空白間距,線越粗,空白越大; 引用虛線的view需要添加屬性android:layerType,值設為"software",否則顯示不了虛線。

ring

首先,shape根元素有些屬性隻适用于ring類型,先過目下這些屬性吧: android:innerRadius 内環的半徑 android:innerRadiusRatio 浮點型,以環的寬度比率來表示内環的半徑,預設為3,表示内環半徑為環的寬度除以3,該值會被android:innerRadius覆寫 android:thickness 環的厚度 android:thicknessRatio 浮點型,以環的寬度比率來表示環的厚度,預設為9,表示環的厚度為環的寬度除以9,該值會被android:thickness覆寫 android:useLevel 一般為false,否則可能環形無法顯示,隻有作為LevelListDrawable使用時才設為true

shape隻能定義單一的形狀,而實際應用中,很多地方比如按鈕、Tab、ListItem等都是不同狀态有不同的展示形狀。舉個例子,一個按鈕的背景,預設時是一個形狀,按下時是一個形狀,不可操作時又是另一個形狀。有時候,不同狀态下改變的不隻是背景、圖檔等,文字顔色也會相應改變。而要處理這些不同狀态下展示什麼的問題,就要用selector來實作了。

那麼,看看都有哪些狀态可以設定呢: android:state_enabled: 設定觸摸或點選事件是否可用狀态,一般隻在false時設定該屬性,表示不可用狀态 android:state_pressed: 設定是否按壓狀态,一般在true時設定該屬性,表示已按壓狀态,預設為false android:state_selected: 設定是否選中狀态,true表示已選中,false表示未選中 android:state_checked: 設定是否勾選狀态,主要用于CheckBox和RadioButton,true表示已被勾選,false表示未被勾選 android:state_checkable: 設定勾選是否可用狀态,類似state_enabled,隻是state_enabled會影響觸摸或點選事件,而state_checkable影響勾選事件 android:state_focused: 設定是否獲得焦點狀态,true表示獲得焦點,預設為false,表示未獲得焦點 android:state_window_focused: 設定目前視窗是否獲得焦點狀态,true表示獲得焦點,false表示未獲得焦點,例如拉下通知欄或彈出對話框時,目前界面就會失去焦點;另外,ListView的ListItem獲得焦點時也會觸發true狀态,可以了解為目前視窗就是ListItem本身 android:state_activated: 設定是否被激活狀态,true表示被激活,false表示未激活,API Level 11及以上才支援,可通過代碼調用控件的setActivated(boolean)方法設定是否激活該控件 android:state_hovered: 設定是否滑鼠在上面滑動的狀态,true表示滑鼠在上面滑動,預設為false,API Level 14及以上才支援

使用layer-list可以将多個drawable按照順序層疊在一起顯示。

帶陰影的圓角矩形

從上面的示例代碼可以看到,layer-list可以作為根節點,也可以作為selector中item的子節點。layer-list可以添加多個item子節點,每個item子節點對應一個drawable資源,按照item從上到下的順序疊加在一起,再通過設定每個item的偏移量就可以看到陰影等效果了。layer-list的item可以通過下面四個屬性設定偏移量: android:top 頂部的偏移量 android:bottom 底部的偏移量 android:left 左邊的偏移量 android:right 右邊的偏移量 這四個偏移量和控件的margin設定差不多,都是外間距的效果。如何不設定偏移量,前面的圖層就完全擋住了後面的圖層,進而也看不到後面的圖層效果了。 另外,關于item的用法,也做下總結: 根節點不同時,可設定的屬性是會不同的,比如selector下,可以設定一些狀态屬性,而在layer-list下,可以設定偏移量; 就算父節點同樣是selector,放在drawable目錄和放在color目錄下可用的屬性也會不同,比如drawable目錄下可用的屬性為android:drawable,在color目錄下可用的屬性為android:color; item的子節點可以為任何類型的drawable類标簽,除了上面例子中的shape、color、layer-list,也可以是selector,還有其他沒講過的bitmap、clip、scale、inset、transition、rotate、animated-rotate、lever-list等等。
nine-patch标簽 使用nine-patch标簽可以對點九圖檔做一些設定處理,不過可設定的屬性并不多: android:src 必填項,必須指定點九類型的圖檔 android:dither 設定是否抖動,圖檔與螢幕的像素配置不同時會用到,比如圖檔是ARGB 8888的,而螢幕是RGB565 android:tint 給圖檔着色,比如圖檔本來是黑色的,着色後可以變成白色 android:tintMode 着色模式,API Level 21(Android 5.0)才添加的屬性 android:alpha 設定圖檔的透明度,取值範圍為0.0~1.0之間,0.0為全透明,1.0為全不透明,API Level最低要求是11 android:autoMirrored 設定圖檔是否需要鏡像反轉,當布局方向是RTL,即從右到左布局時才有用,API Level 19(Android 4.4)才添加的屬性 scale标簽 使用scale标簽可以對drawable進行縮放操作,和clip一樣是通過設定level來控制縮放的比例。scale标簽可以設定的屬性如下: android:drawable 指定drawable資源,如果不設定該屬性,也可以定義drawable類型的子标簽 android:scaleHeight 設定可縮放的高度,用百分比表示,格式為XX%,0%表示不做任何縮放,50%表示隻能縮放一半 android:scaleWidth 設定可縮放的寬度,用百分比表示,格式為XX%,0%表示不做任何縮放,50%表示隻能縮放一半 android:scaleGravity 設定drawable縮放後的位置,取值和bitmap标簽的一樣,就不一一列舉說明了,不過預設值是left android:useIntrinsicSizeAsMinimum 設定drawable原有尺寸作為最小尺寸,設為true時,縮放基本無效,API Level最低要求為11 rotate标簽 使用rotate标簽可以對一個drawable進行旋轉操作,在shape篇講環形時最後舉了個進度條時就用到了rotate标簽。另外,比如你有一張箭頭向上的圖檔,但你還需要一個箭頭向下的圖檔,這時就可以使用rotate将向上的箭頭旋轉變成一張箭頭向下的drawable。 先看看rotate标簽的一些屬性吧: android:fromDegrees 起始的角度度數 android:toDegrees 結束的角度度數,正數表示順時針,負數表示逆時針 android:pivotX 旋轉中心的X坐标,浮點數或是百分比。浮點數表示相對于drawable的左邊緣距離

引用官方文檔的話

Drawable animation lets you load a series of Drawable resources one after another to create an animation. This is a traditional animation in the sense that it is created with a sequence of different images, played in order, like a roll of film.

其實說明動畫的Drawable的資源按照一定順序執行,最終出來的效果類似電影中一幀一幀的,它允許你實作像播放幻燈片一樣的效果。

是它的根元素,做為根節點,下面就是一個例子

這裡定義了三個drawable資源檔案,每次執行時間為200ms,順序是從上到下,這種動畫最常見應用場景是在想表達電池充電的過程,從0%,25%,50%,100%表達連續充電的過程,就可以做四個不同的資源圖檔,然後按照一定的順序,進而執行相應的運作時間。

有了動畫檔案之後,具體怎麼用呢,如下:

特别注意,AnimationDrawable的start()方法不能在Activity的onCreate方法中調運,因為AnimationDrawable還未完全附着到window上,是以最好的調運時機是onWindowFocusChanged()方法中。

其中Drawable Animation還有一個animated-rotate屬性來定義旋轉動畫,這個用法也是類似的,不再過多講述。

引用官方文檔

You can use the view animation system to perform tweened animation on Views. Tween animation calculates the animation with information such as the start point, end point, size, rotation, and other common aspects of an animation.

視圖動畫,也叫Tween(補間)動畫可以在一個視圖容器内執行一系列簡單變換(位置、大小、旋轉、透明度)。譬如,如果你有一個TextView對象,您可以移動、旋轉、縮放、透明度設定其文本,當然,如果它有一個背景圖像,背景圖像會随着文本變化。

補間動畫通過XML或Android代碼定義,建議使用XML檔案定義,因為它更具可讀性、可重用性。

Animation控制的是整個View,實作的原理是每次繪制視圖時,View所在的ViewGroup的drawChild函數擷取該View的Animation的Transformation值,然後調用canvas.concat(transformToApply.getMatrix()),通過矩陣運算完成動畫幀。如果動畫沒完成,就繼續調用invalidate()函數,啟動下次繪制來驅動動畫,進而完成整個動畫的繪制。

視圖動畫使用簡單,主要有以下四種類型動畫:

Alpha Animation

Rotate Animation

Translate Animation

Scale Animation

并提供了AnimationSet動畫集合,混合使用多種動畫方式,在Android 3.0之前,View Animation一家獨大,但是随着Property Animation的推出,風光就大不如前,相比屬性動畫,視圖動畫一個最大的缺陷是不具備互動性,當某個元素發生視圖動畫後,其響應的事件的位置還依然在動畫前的地方,是以視圖動畫隻能做普通的動畫效果,避免互動的發生,但它的優點是,效率高而且使用友善。

可以實作透明度漸變的動畫效果,也就是淡入淡出的效果,可通過設定下面三個屬性來設定淡入或淡出效果: android:duration 動畫從開始到結束持續的時長,機關為毫秒 android:fromAlpha 動畫開始時的透明度,0.0為全透明,1.0為不透明,預設為1.0 android:toAlpha 動畫結束時的透明度,0.0為全透明,1.0為不透明,預設為1.0 當設定開始時透明度為0.0,結束時為1.0,就能實作淡入效果;相反,當設定開始時透明度為1.0,結束時為0.0,那就能實作淡出效果。示例代碼如下:

将這動畫效果添加到View上也隻需要一行代碼:

可以實作旋轉的動畫效果,主要的屬性如下: android:fromDegrees 旋轉開始的角度 android:toDegrees 旋轉結束的角度 android:pivotX 旋轉中心點的X坐标,純數字表示相對于View本身左邊緣的像素偏移量;帶"%"字尾時表示相對于View本身左邊緣的百分比偏移量;帶"%p"字尾時表示相對于父View左邊緣的百分比偏移量 android:pivotY 旋轉中心點的Y坐标,純數字表示相對于View本身頂部邊緣的像素偏移量;帶"%"字尾時表示相對于View本身頂部邊緣的百分比偏移量;帶"%p"字尾時表示相對于父View頂部邊緣的百分比偏移量 以下示例代碼旋轉角度從0到360,即旋轉了一圈,旋轉的中心點都設為了50%,即是View本身中點的位置。

标簽對應的類為RotateAnimation,父類也是Animation,添加到View上的代碼如下:

可以實作位置移動的動畫效果,可以是垂直方向的移動,也可以是水準方向的移動。坐标的值可以有三種格式:從-100到100,以"%"結束,表示相對于View本身的百分比位置;如果以"%p"結束,表示相對于View的父View的百分比位置;如果沒有任何字尾,表示相對于View本身具體的像素值。主要的屬性如下: android:fromXDelta 起始位置的X坐标的偏移量 android:toXDelta 結束位置的X坐标的偏移量 android:fromYDelta 起始位置的Y坐标的偏移量 android:toYDelta 結束位置的Y坐标的偏移量 看示例吧,以下代碼實作的是從左到右的移動效果,起始位置為相對于控件本身-100%的位置,即在控件左邊,與控件本身寬度一緻的位置;結束位置為相對于父控件100%的位置,即會移出父控件右邊緣的位置。

标簽對應的類為TranslateAnimation,父類也是Animation,添加到View上的代碼如下:

可以實作縮放的動畫效果,主要的屬性如下: android:fromXScale 動畫開始時X坐标上的縮放尺寸 android:toXScale 動畫結束時X坐标上的縮放尺寸 android:fromYScale 動畫開始時Y坐标上的縮放尺寸 android:toYScale 動畫結束時Y坐标上的縮放尺寸 PS:以上四個屬性,0.0表示縮放到沒有,1.0表示正常無縮放,小于1.0表示收縮,大于1.0表示放大 android:pivotX 縮放時的固定不變的X坐标,一般用百分比表示,0%表示左邊緣,100%表示右邊緣 android:pivotY 縮放時的固定不變的Y坐标,一般用百分比表示,0%表示頂部邊緣,100%表示底部邊緣 具體示例:

對應的類為ScaleAnimation,父類也是Animation,添加到View上的用法和AlphaAnimation一樣,代碼如下:

标簽可以将多個動畫組合起來,變成一個動畫集。比如想将一張圖檔縮放的同時也做移動,這時候就要用set标簽組合縮放動畫和移動動畫了。示例代碼如下:

以上代碼實作的動畫效果為向右移動的同時也同步放大。Set标簽在視圖動畫中除了可以組合Alpha ,Rotate , Scale , Scale 這四種标簽,也可以嵌套其他Set标簽。

The property animation system is a robust framework that allows you to animate almost anything. You can define an animation to change any object property over time, regardless of whether it draws to the screen or not. A property animation changes a property's (a field in an object) value over a specified length of time. To animate something, you specify the object property that you want to animate, such as an object's position on the screen, how long you want to animate it for, and what values you want to animate between

視圖動畫隻能作用于View,而且視圖動畫改變的隻是View的繪制效果,View真正的屬性并沒有改變。比如,一個按鈕做平移的動畫,雖然按鈕的确做了平移,但按鈕可點選的區域并沒随着平移而改變,還是在原來的位置。而屬性動畫則可以改變真正的屬性,進而實作按鈕平移時點選區域也跟着平移。通俗點說,屬性動畫其實就是在一定時間内,按照一定規律來改變對象的屬性,進而使對象展現出動畫效果。

屬性動畫是在android 3.0引入的動畫體系,如果還想适配基本已經滅絕的2.x版本,隻好繞道了。

屬性動畫和視圖動畫一樣,可以通過xml檔案定義,不同的是,視圖動畫的xml檔案放于res/anim/目錄下,而屬性動畫的xml檔案則放于res/animator/目錄下。一個是anim,一個是animator,别搞錯了。同樣的,在Java代碼裡引用屬性動畫的xml檔案時,則用R.animator.filename,不同于視圖動畫,引用時為R.anim.filename。

屬性動畫主要有三個元素:animator,objectAnimator,set

相對應的有三個類:ValueAnimator、ObjectAnimator、AnimatorSet。

ValueAnimator是基本的動畫類,處理值動畫,通過監聽某一值的變化,進行相應的操作。ObjectAnimator是ValueAnimator的子類,處理對象動畫。AnimatorSet則為動畫集,可以組合另外兩種動畫或動畫集。相應的三個标簽元素的關系也一樣。

樣式開發主要還是用xml的形式,是以這裡先主要還是講标簽的用法。

animator标簽與對應的ValueAnimator類提供了屬性動畫的核心功能,包括計算動畫值、動畫時間細節、是否重複等。執行屬性動畫分兩個步驟: 計算動畫值 将動畫值應用到對象和屬性上 ValuAnimiator隻完成第一步,即隻計算值,要實作第二步則需要在值變化的監聽器裡自行更新對象屬性。 通過animator标簽可以很友善的對ValuAnimiator進行設定,可設定的屬性如下: android:startOffset 設定動畫執行之前的等待時長,機關為毫秒 android:repeatCount 設定動畫重複執行的次數,預設為0,即不重複;可設為-1或infinite,表示無限重複 android:repeatMode 設定動畫重複執行的模式,可設為以下兩個值其中之一: restart 動畫重複執行時從起點開始,預設為該值 reverse 動畫會反方向執行 android:valueFrom 動畫開始的值,可以為int值、float值或color值 android:valueTo 動畫結束的值,可以為int值、float值或color值 android:valueType 動畫值類型,若為color值,則無需設定該屬性 intType 指定動畫值,即以上兩個value屬性的值為整型 floatType 指定動畫值,即以上兩個value屬性的值為浮點型,預設值 android:interpolator 設定動畫速率的變化,比如加速、減速、勻速等,需要指定Interpolator資源。 接着,用一個執行個體講解具體的用法吧。在這個例子裡,将一個按鈕的寬度進行縮放,從100%縮放到20%。 xml檔案的代碼如下:

可看到,值的變化從100到20,動畫時長3000毫秒,以下則是目标按鈕的xml代碼:

按鈕預設是填充螢幕寬度的,點選時的執行方法為onScaleWidth,以下則是onScaleWidth方法的代碼:

從中,我們可以看到屬性動畫則是通過AnimatorInflater類的loadAnimation()方法擷取相應的Animator類執行個體。另外,ValueAnimator通過添加AnimatorUpdateListener監聽器監聽值的變化,進而再手動更新目标對象的屬性。最後,通過調用valueAnimator.start()方法啟動動畫。

objectAnimator标簽對應的類為ObjectAnimator,為ValueAnimator的子類。objectAnimator标簽與标簽animator不同的是,可以直接指定動畫的目标對象的屬性。标簽可設定的屬性除了和一樣的那些,另外多了一個: android:propertyName 目标對象的屬性名,要求目标對象必須提供該屬性的setter方法,如果動畫的時候沒有初始值,還需要提供getter方法 還是用執行個體說明具體用法,還是用上面的例子,将一個按鈕的寬度進行縮放,從100%縮放到20%,但這次改用objectAnimator實作。

與上面animator标簽方式做對比,就隻是多了一個android:propertyName的屬性,設定值為width。也就是說,動畫改變的屬性為width,值将從100逐漸減到20。另外,值是從setWidth()傳遞過去的,再從getWidth()擷取。而且,這裡設定的值代表的是比例值,是以,還需要進行計算轉化為實際的寬度值。最後,對象實際的寬度值為view.getLayoutParams().width。是以,需要用一個包裝類來包裝原始的view對象,對其提供setWidth()和getWidth()方法,代碼如下:

上面setWidth()的代碼裡,根據比例值轉化為了實際的寬度值。最後,動畫處理的代碼如下:

ObjectAnimator提供了屬性的設定,但相應的需要有該屬性的setter和getter方法。而ValueAnimator則隻是定義了值的變化,并不指定目标屬性,是以也不需要提供setter和getter方法,但隻能在AnimatorUpdateListener監聽器裡手動更新屬性。不過,也因為沒有指定屬性,是以其實更具靈活性了,你可以在監聽器裡根據值的變化做任何事情,比如更新多個屬性,比如在縮放寬度的同時做垂直移動。 為了對View更友善的設定屬性動畫,Android系統也提供了View的一些屬性和相應的setter和getter方法: alpha:透明度,預設為1,表示不透明,0表示完全透明 pivotX 和 pivotY:旋轉的軸點和縮放的基準點,預設是View的中心點 scaleX 和 scaleY:基于pivotX和pivotY的縮放,1表示無縮放,小于1表示收縮,大于1則放大 rotation、rotationX 和 rotationY:基于軸點(pivotX和pivotY)的旋轉,rotation為平面的旋轉,rotationX和rotationY為立體的旋轉 translationX 和 translationY:View的螢幕位置坐标變化量,以layout容器的左上角為坐标原點 x 和 y:View在父容器内的最終位置,是左上角坐标和偏移量(translationX,translationY)的和

set标簽對應于AnimatorSet類,可以将多個動畫組合成一個動畫集,如上面提到的在縮放寬度的同時做垂直移動,可以将一個縮放寬度的動畫和一個垂直移動的動畫組合在一起。 set标簽有一個屬性可以設定動畫的時序關系: android:ordering 設定動畫的時序關系,取值可為以下兩個值之一:together 動畫同時執行,預設值sequentially 動畫按順序執行 那如果想有些動畫同時執行,有些按順序執行,該怎麼辦呢?因為set标簽是可以嵌套其他set标簽的,也就是說可以将同時執行的組合在一個set标簽,再嵌在按順序執行的set标簽内。

以上代碼可實作兩個同時執行的動畫,一個将width從100縮放到20,一個将marginTop從0增加到100。多了一個marginTop屬性,那麼,在ViewWrapper添加setMarginTop()方法,添加後的ViewWrapper類代碼如下:

最後,動畫處理的代碼:

這樣就實作了寬度縮放和垂直移動的效果。

當然,在Android3.0之後,Google給View增加了animate方法來直接驅動屬性動畫,代碼如下:

目前到此為止,我們了解到在Android中有三種不同的動畫類型,在Android3.0版本其實是一個區分點,在3.0之前用的居多都是View Animation,而在3.0之後用的居多是Property Animation,本次介紹的是這三者之間的差別和不同用法,下篇介紹具體執行個體和自定義動畫方面的知識點,敬請期待。

源于對掌握的Android開發基礎點進行整理,羅列下已經總結的文章,從中可以看到技術積累的過程。

1,Android系統簡介

2,ProGuard代碼混淆

3,講講Handler+Looper+MessageQueue關系

4,Android圖檔加載庫了解

5,談談Android運作時權限了解

6,EventBus初了解

7,Android 常見工具類

8,對于Fragment的一些了解

9,Android 四大元件之 " Activity "

10,Android 四大元件之" Service "

11,Android 四大元件之“ BroadcastReceiver "

12,Android 四大元件之" ContentProvider "

13,講講 Android 事件攔截機制

14,Android 動畫的了解

15,Android 生命周期和啟動模式

16,Android IPC 機制

17,View 的事件體系

18,View 的工作原理

19,了解 Window 和 WindowManager

20,Activity 啟動過程分析

21,Service 啟動過程分析

22,Android 性能優化

23,Android 消息機制

24,Android Bitmap相關

25,Android 線程和線程池

26,Android 中的 Drawable 和動畫

27,RecylerView 中的裝飾者模式

28,Android 觸摸事件機制

29,Android 事件機制應用

30,Cordova 架構的一些了解

31,有關 Android 插件化思考

32,開發人員必備技能——單元測試

上一篇: 日志切割