幀動畫和補間動畫

arthur_8 8年前發布 | 5K 次閱讀 安卓開發 Android開發 移動開發

寫在前面:

為了使用戶的交互更加流暢自然,動畫也就成為了一個應用中必不可少的元素之一。在 Android 中常用的動畫分類無外乎三種,最早的 幀動畫補間動畫 ,以及 3.0 之后加入的 屬性動畫 ,是它們組成了 Android 中各種炫酷亮眼的動畫效果。

關于動畫相關的博文說實話很多,但是為什么要寫這篇文章呢?因為我發現很多博客都上來就“翻譯”了一通 API ,這對很多沒有建立起 Android 動畫體系概念的新人來說,非常不友好。既沒有說明各種動畫的應用場景,也沒有橫向對比動畫的優缺點。對于剛學習動畫的同學來說,他們讀起來心里就更沒底了,面對稍微復雜的動畫就無從下手,就好比那句歌詞“懂得很多道理,卻仍過不好這一生”。所以本文要有更多思考分析之外,也會教大家一些關于動畫的小技巧和可能踩到的坑。本文我們就先來研究 幀動畫 和 補間動畫,話不多說,現在開始我們的內容吧。

幀動畫

我們由簡到難,先來講講幀動畫。幀動畫就是 Frame 動畫,它的原理十分“復古”,和我們小時候看的動畫片原理一致(注意是我們小時候),就是把一張張準備好的,一系列圖片,按照指定的時間播放出來,從而達到動畫的效果。

如此簡單而又看似過時的幀動畫,是否就被淘汰了呢?答案的自然是否定的。幀動畫依然在這個復雜而有機的 Android 系統中占有一席之地。先來告訴大家幀動畫的使用場景吧。

  • 設備的開機動畫

  • 及其“復雜”的效果,看似不可能完成的動畫

設備的開機動畫界面這個沒什么好解釋的,據我所知市面上99%的機器都是這么做的,因為這個時候系統或資源還沒準備完全,所以就肯定會選擇幀動畫。

我在我以前的魅族手機 /system/media 文件夾下,找到了一系列以上這種圖片,組合到一起就是開機動畫了。

你可能還對我上面所說的第二種使用場景表示懷疑,前幾天我看到一個應用有一個非常酷炫的效果,3D特效旋轉的畫面,請腦補一下數碼寶貝進化的樣子,我剛開始還納悶,這個用代碼怎么實現啊,想了下我想通了,這個用幀動畫其實最好實現了,難為的可能就是設計師了( 那可就不關能怪我推責任了哦~)。

介紹完了應用場景,那現在就應該來介紹到底如何在代碼中使用了。

準備一個幀動畫的圖片資源:

可以通過 代碼 或者 xml 方式來使用 幀動畫

XML

新建工程,然后在 drawable 目錄下新建一個 xml 文件,名字是 bear_anim ,代碼如下:

<?xml version="1.0" encoding="utf-8"?>
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
 android:oneshot="false">

 <item
 android:drawable="@drawable/sp1"
 android:duration="200" />
 <item
 android:drawable="@drawable/sp2"
 android:duration="200" />
 <item
 android:drawable="@drawable/sp3"
 android:duration="200" />
 <item
 android:drawable="@drawable/sp4"
 android:duration="200" />
 <item
 android:drawable="@drawable/sp5"
 android:duration="200" />
 <item
 android:drawable="@drawable/sp6"
 android:duration="200" />
 <item
 android:drawable="@drawable/sp7"
 android:duration="200" />
 <item
 android:drawable="@drawable/sp8"
 android:duration="200" />
 <item
 android:drawable="@drawable/sp9"
 android:duration="200" />
</animation-list>

需要注意的是,根節點必須為 <animation-list> , oneshot 屬性代表是否循環播放一次,true 為一次,false 為循環播放。 duration 屬性表示此張圖片滯留的時間,然后注意從上到下依次引用圖片即可。

接著給一個 ImageView 設置這個動畫:

<ImageView
 android:id="@+id/iv_frame"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:background="@drawable/bear_anim"
 android:layout_centerInParent="true" />

最后一步當然是讓動畫跑起來了,需要用到 AnimationDrawable 對象:

AnimationDrawable animationDrawable = (AnimationDrawable) ivFrame.getBackground();
 animationDrawable.start();

這樣一個幀動畫就展現在我們面前了,想讓它停下來也很簡單:

if(animationDrawable.isRunning()){
 animationDrawable.stop();
}

自然我們也可以用純代碼的方式實現,不過在此真的不推薦,顯然 xml 的方式更省力,并且維護起來更方便。

補間動畫

tween 動畫也叫作補間動畫,它可以在一定的時間內使 View 完成四種基本的動畫,即 平移、縮放、透明度、旋轉 ,也可以將它們組合到一起播放出來。這里先提一下未來會研究的 屬性動畫 ,也許從上面可以觀察到, 無論是 幀動畫 還是 補間動畫 ,都是把動畫效果作用到 View 上,如果一個不是 View 的元素想實現動畫,那這兩種就無能為力了,只能請 屬性動畫 幫忙了。

并且補間動畫僅僅是給 View 增加了動畫的“假象”,比如一個按鈕從左側跑到了右側,你在右側是無法點擊它的,但是這不代表 補間動畫就沒有用武之地了,當你需要的動畫效果無外乎上面那四種動畫,并且僅僅是展示的時候,補間動畫就再合適不過了。

同樣,補間動畫的實現依然可以有兩種方式,xml 定義或者是純代碼的方式,這里依然是建議使用 xml 的方式。

AlphaAnimation 透明度

在 res 文件夾下新建文件夾 anim ,新建文件 alpha_anim:

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
 android:duration="200"
 android:fillAfter="true"
 android:fromAlpha="0"
 android:interpolator="@android:anim/linear_interpolator"
 android:repeatCount="-1"
 android:repeatMode="reverse"
 android:shareInterpolator="false"
 android:toAlpha="1">

</alpha>

alpha 是透明度動畫,分別介紹一下屬性,共用屬性下文不再重復介紹。

duration 表示這一次動畫持續的時間

fillAfter 表示動畫結束時,是否保持最后一幀的樣子

fillBefore 表示動畫結束時,是否保持第一幀的樣子

repeatCount 表示動畫循環的次數,默認為 0 次不循環,-1 為無限循環。

repeatMode 表示是循環的模式,reverse 是從一次動畫結束開始,restart 是從動畫的開始處循環

interpolator 是一個插值器資源,它可以控制動畫的播放速度

shareInterpolator 表示是否與 set 中其他動畫共享插值器,false為各自使用各自的插值器

上面共有的屬性講完了,下面來說 AlphaAnimation 特有的屬性

fromAlpha 表示動畫開始時的透明度

toAlpha 表示動畫結束時候的透明度

取值為[0.0,1.0],0代表完全透明,1代表不透明。

代碼中借助 AnimationUtils 類來加載調用

Animation alpha = AnimationUtils.loadAnimation(this, R.anim.alpha_anim);
ivFrame.startAnimation(alpha);

以下的三種動畫調用同理。

RotateAnimation 旋轉動畫

新建 xml 文件,rotate_anim

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
 android:duration="200"
 android:fromDegrees="0"
 android:pivotX="50%"
 android:pivotY="50%"
 android:toDegrees="360">

</rotate>

fromDegrees 起始角度 單位度 浮點值

toDegrees 結尾角度 單位度 浮點值

pivotX 旋轉中心點的 X 坐標,這個數值有三種表達方式

pivotY 旋轉中心丶的 Y 坐標,這個數值也有三種表達方式

  • 純數字 例如 20 ,代表相對于自身左邊緣或頂邊緣 + 20 像素
  • num% 代表 相對于自身左邊緣或頂邊緣 + 自身寬 的百分之 num
  • num%p 代表相對于自身左邊緣或頂邊緣 + 父容器 的百分之 num

ScaleAnimation 縮放動畫

<scale xmlns:android="http://schemas.android.com/apk/res/android"
 android:duration="2000"
 android:fromXScale="0.5"
 android:fromYScale="0.5"
 android:pivotX="50%"
 android:pivotY="50%"
 android:toXScale="2.0"
 android:toYScale="2.0">

</scale>

fromXScale
fromYScale

代表縮放時,X/Y 坐標起始大小,浮點值,0.5代表自身的一半,2.0代表自身的兩倍大小。

toXScale
toYScale

代表縮放時,X/Y 縮放結束時候大小。

pivotX
pivotY

縮放的中心坐標,單位與上面 RotateAnimation 介紹的同理

TranslateAnimation 平移動畫

新建 xml 文件 translate_anim

<translate xmlns:android="http://schemas.android.com/apk/res/android"
 android:duration="200"
 android:fromXDelta="0"
 android:fromYDelta="0"
 android:toXDelta="100%"
 android:toYDelta="100%">

</translate>

fromXDelta
fromYDelta

起始時,X/Y 方向的位置

toXDelta
toYDelta

終止時,X/Y 方向的位置

這四個屬性都支持同樣的單位,依然是三種表達方式,浮點數、num% 和 num%p

  • 浮點數 位置為 View 的左邊距/上邊距 + 此數值 正數為右,負數為左
  • num% 位置為 View 的左邊距/上邊距 + View寬的百分之num 正數為右,負數為左
  • num%p 位置為 View 的左邊距/上邊距 + 父容器的百分之num 正數為右,負數為左

如果想將幾個動畫組合起來使用,可以選擇跟布局節點為 set

<set xmlns:android="http://schemas.android.com/apk/res/android"
 android:duration="200">

 <translate
 android:fromXDelta="0"
 android:fromYDelta="0"
 android:toXDelta="100%"
 android:toYDelta="100%">
 </translate>

 <rotate
 android:fromDegrees="0"
 android:pivotX="50%"
 android:pivotY="50%"
 android:toDegrees="360">
 </rotate>

</set>

代碼中組合動畫的實現方式:

Animation alpha = AnimationUtils.loadAnimation(this, R.anim.alpha_anim);
Animation translate = AnimationUtils.loadAnimation(this, R.anim.translate_anim);
AnimationSet set = new AnimationSet(false);
set.addAnimation(alpha);
set.addAnimation(translate);
ivFrame.startAnimation(set);

到這里四種補間動畫終于算是介紹完成了,下面在帶來一點技巧

alpha.setAnimationListener(new Animation.AnimationListener() {
 @Override
 public void onAnimationStart(Animation animation) {

 }

 @Override
 public void onAnimationEnd(Animation animation) {

 }

 @Override
 public void onAnimationRepeat(Animation animation) {

 }
 });

給動畫設置一個偵聽,在一些回調中做你的操作。

停止一個補間動畫的正確姿勢:

public void stopAnimation(View v) {
 v.clearAnimation();
 if (canCancelAnimation()) {
 v.animate().cancel();
 }
 animation.setAnimationListener(null);
 v.setAnimation(null);
}
public static boolean canCancelAnimation() {
 return Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH;
}

啊哈,終于完成本文了,希望大家遇到動畫的需求不要慫,拿起鍵盤開寫就對了,未來會給大家帶來 屬性動畫 的教程。

 

來自:https://itsmelo.github.io/2016/10/31/幀動畫和補間動畫/

 

 本文由用戶 arthur_8 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!