Android的動畫可以分為三種:View動畫、幀動畫和屬性動畫。
- View動畫包括:平移、旋轉、縮放、透明度。不會改變控制元件座標引數
- 幀動畫:圖片切換動畫。不會改變控制元件座標引數
- 屬性動畫:通過動態改變控制元件的屬性(改變控制元件部分座標引數)達到動畫效果。
一 View動畫的建立步驟和方式
View動畫的四種變換效果對應著Animation的四個子類,分別是:TranslateAnimation,RotateAnimation,ScaleAnimation,AlphaAnimation。這四種動畫既可以通過XML來定義,也可以通過程式碼來動態建立。他們的整合關係如下:
通過xml去建立動畫的步驟:
1.在res資料夾下建立anim資料夾
2.在anim資料夾下去建立動畫xml檔案
3.通過AnimationUtils類的靜態方法loadAnimation獲取動畫物件
4.通過View.startAnimation()方法開啟動畫;
通過程式碼去建立動畫的步驟(這裡不寫具體的步驟):
1.建立TranslateAnimation、RotateAnimation、ScaleAnimation或AlphaAnimation物件;
2.設定建立的動畫物件的屬性,如動畫執行時間、延遲時間、起始位置、結束位置等;
3.通過View.startAnimation()方法開啟動畫;
二 TranslateAnimation動畫
建立一個動畫xml檔案
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="300"
android:toYDelta="300" />複製程式碼
解釋一下屬性:
這裡的座標系是以控制元件自身的左上角為座標原點,右下為正方向的座標系
android:fromXDelta:動畫開始時候X方向的座標
android:fromYDelta:動畫開始時候Y方向的座標
android:toXDelta:動畫結束時候X方向的座標
android:toYDelta:動畫結束時候Y方向的座標
它們的值不僅可以指定畫素,而且還可以指定百分比,且座標系的原點不會改變!
相對於自身可以指定像這樣:
android:toXDelta="100%"複製程式碼
相對於父控制元件可以指定像這樣
android:toXDelta="100%p"複製程式碼
android:duration:一個動畫週期持續時間,單位是ms
android:fillAfter :設定為true,動畫結束時,將保持動畫最後時的狀態
android:fillBefore :設定為true,動畫結束時,還原到開始動畫前的狀態,預設值
android:repeatCount :重複次數,想讓永遠設定成-1
android:repeatMode :重複型別,有reverse和restart兩個值,reverse表示倒序回放,restart表示重新放一遍,必須與repeatCount一起使用才能看到效果。因為這裡的意義是重複的型別,即回放時的動作。預設不寫是restart效果
android:startOffset:動畫延遲執行的時間,單位是ms
android:interpolator:動畫插值器,改變動畫播放速率
插值器的值有:
@android:anim/accelerate_interpolator:加速變化(開始慢,越來越快)
@android:anim/decelerate_interpolator:減速變化(開始快,越來越慢)
@android:anim/accelerate_decelerate_interpolator:先加速後減速(中間速度最快)
@android:anim/linear_interpolator:線性均勻變化
@android:anim/overshoot_interpolator:超出結尾的臨界值,然後在緩慢回到結束值
@android:anim/anticipate_interpolator:先向相反的方向改變一點,然後加速變化
@android:anim/anitcipate_overshoot_interpolator:先向相反的方向改變一點,然後在加速播放至超出結束值一點,然後在緩慢回到結束值
@android:anim/bounce_interpolator:動畫快結束的時候,模擬球落地的回彈效果
@android:anim/cycle_interpolator:反方向在做一次動畫效果
程式碼載入xml去開啟動畫程式碼:
//載入xml動畫
val translate1 = AnimationUtils.loadAnimation(this, R.anim.translate1)
//給控制元件設定動畫並開啟
btn.startAnimation(translate1)複製程式碼
三RotateAnimation動畫
建立一個動畫xml檔案
<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromDegrees="0"
android:toDegrees="-300"
android:pivotX="50%"
android:pivotY="50%">
</rotate>複製程式碼
解釋一下屬性:
這裡的夾角是和Y軸的夾角,順時針為正,逆時針為負,座標系還是當前控制元件的左上角為原點
android:fromDegrees:開始動畫的角度
android:toDegrees:結束時候的角度
android:pivotY,android:pivotX:旋轉的中心點座標,不寫是控制元件的左上角原點為中心點
其餘的屬性和平移動畫一樣,不再重複
四 ScaleAnimation動畫
建立一個動畫xml檔案
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1.5"
android:toYScale="1.5">
</scale>複製程式碼
解釋一下屬性:
座標系還是當前控制元件的左上角為原點
android:fromYScale,android:fromXScale:開始縮放比例
android:toXScale, android:toYScale:結束縮放比例
android:toYScale,android:pivotY:縮放中心點
其餘的屬性和平移動畫一樣,不再重複
五AlphaAnimation動畫
<?xml version="1.0" encoding="utf-8"?>
<alpha xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.0">
</alpha>複製程式碼
解釋一下屬性:
android:fromAlpha:動畫開始時候透明度
android:fromAlpha:動畫結束時候透明度
其餘的屬性和平移動畫一樣,不再重複
六組合到一起
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="10000">
<translate
android:fromXDelta="0"
android:fromYDelta="0"
android:toXDelta="0"
android:toYDelta="300" />
<rotate
android:fromDegrees="0"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="300" />
<scale
android:fromXScale="0"
android:fromYScale="0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="1"
android:toYScale="1" />
<alpha
android:fromAlpha="0"
android:toAlpha="1" />
</set>複製程式碼
這裡有兩個細節需要注意:
- 如果我們給set設定了共有的屬性,那麼它包裹的動畫再次設定這個屬性也不會生效,都會以跟屬性為準。
- 但是插值器可以單獨設定,需要配合android:shareInterpolator一起設定,表示集合中的動畫是否和集合共享同一個插值器。
- 如果不想讓組合動畫同時執行,我們可以通過設定動畫的延遲時間去改變不去同時執行,它並沒有像屬性動畫那樣給我們提供設定執行先後順序的方法。
七View動畫的監聽
val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.enter)
loadAnimation.setAnimationListener(object : Animation.AnimationListener {
//動畫完全結束時候呼叫
override fun onAnimationEnd(animation: Animation?) {
}
//動畫開始時候呼叫
override fun onAnimationStart(animation: Animation?) {
}
//動畫重複時候呼叫
override fun onAnimationRepeat(animation: Animation?) {
}
})複製程式碼
八幀動畫
幀動畫是順序播放一組預先定義好的圖片,類似於電影播放。幀動畫建立的檔案在drawable資料夾下。需要用到的類是AnimationDrawable。它的繼承關係如下:
<?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/d_beishang" android:duration="500" />
<item android:drawable="@drawable/d_bishi" android:duration="500" />
<item android:drawable="@drawable/d_bizui" android:duration="500" />
<item android:drawable="@drawable/d_chanzui" android:duration="500" />
</animation-list>複製程式碼
//把定義的幀動畫設定給控制元件
btn.setBackgroundResource(R.drawable.donghua);
//獲取控制元件中的幀動畫
var anim = btn.background as AnimationDrawable
//開啟幀動畫
anim.start()複製程式碼
解釋: android:oneshot屬性表示是否重複動畫,
注意:幀動畫的使用比較簡單,但是比較容易引起OOM。
九view動畫常見應用場景
8.1 5.0版本之前Activity切換動畫
主要用到 overridePendingTransition(int enterAnim,int exitAnim)這個方法,這個方法必須在 startActivity(Intent)或者finish()之後被呼叫才能生效。這裡自定義的view動畫設定到裡邊就能替換原生系統的切換動畫。
延伸:5.0版本之後google對於切換介面動畫提供了新的方式:
8.2給ViewGroup的子控制元件加進場動畫
這種效果需要用到layoutAnimation類,步驟如下:
1.建立res/anim下view動畫
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="100%"
android:toYDelta="0"
android:duration="2000" />
<alpha
android:fromAlpha="0"
android:toAlpha="1"
android:duration="2000" />
</set>複製程式碼
2.在res/anim下建立layoutAnimation
<?xml version="1.0" encoding="utf-8"?>
<layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
android:delay="0.5"
android:animationOrder="normal"
android:animation="@anim/anim_layout">
</layoutAnimation>複製程式碼
解釋屬性:
android:delay:可以取值為數值,百分數,或百分數p。表示兩個子控制元件執行出場動畫的間隔時間,為0時,所有控制元件的動畫沒有延遲全部開始執行;為1時表示等上一個控制元件動畫執行完畢才開始執行下一個
android:animationOrder:有三個值::normal表示按正常順序出現。random表示亂序出現。reverse表示反序出現。
android:animation:指定出現時要執行的view動畫
3.給viewGroup設定layoutAnimation的值
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layoutAnimation="@anim/layout_viewgrop"
android:orientation="vertical">
<Button
android:id="@+id/btn"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
...
</LinearLayout>複製程式碼
同時可以用程式碼設定子view的動畫:
//載入組定義的view動畫
val loadAnimation = AnimationUtils.loadAnimation(this, R.anim.anim_layout)
//建立動畫控制器
val Controller = LayoutAnimationController(loadAnimation)
//設定每個子view動畫間隔
Controller.delay=0.5F
//設定動畫播放順序
Controller.order = LayoutAnimationController.ORDER_NORMAL
//把動畫設定給父控制元件
viewGroup.layoutAnimation = Controller複製程式碼