前言
- 動畫的使用 是
Android
開發中常用的知識 - 可是動畫的種類繁多、使用復雜,每當需要 采用自定義動畫 實現 復雜的動畫效果時,很多開發者就顯得束手無策
- Android中 補間動畫 & 屬性動畫實現動畫的原理是:
其中,步驟2中的 插值器(Interpolator
)和估值器(TypeEvaluator
)是實現 復雜動畫效果的關鍵;本文主要講解 將詳細講解 插值器(Interpolator
),通過閱讀本文你將能輕松實現復雜的動畫效果
Carson帶你學
Android
動畫系列文章:
Carson帶你學Android:一份全面&詳細的動畫知識學習攻略
Carson帶你學Android:常見的三種動畫類型
Carson帶你學Android:補間動畫學習教程
Carson帶你學Android:屬性動畫學習教程
Carson帶你學Android:逐幀動畫學習教程
Carson帶你學Android:自定義動畫神器-估值器(含實例教學)
Carson帶你學Android:自定義動畫神器-插值器(含實例教學)
目錄
1. 簡介
- 定義:Android實現動畫效果中的一個輔助接口
- 作用:設置 屬性值 從初始值過渡到結束值 的變化規律
- 如勻速、加速 & 減速 等等
- 即確定了 動畫效果變化的模式,如勻速變化、加速變化 等等
2. 應用場景
實現非線性運動的動畫效果。非線性運動是指動畫改變的速率不是一成不變的,如加速、減速運動的動畫效果。
3. 具體使用
插值器在動畫的使用有兩種方式:在XML / Java代碼中設置:
/*
* 使用方式1:xml
* 主要是設置插值器屬性 android:interpolator
*/
<?xml version="1.0" encoding="utf-8"?>
<scale xmlns:android="http://schemas.android.com/apk/res/android"
// 通過資源ID設置插值器
android:interpolator="@android:anim/overshoot_interpolator"
android:duration="3000"
android:fromXScale="0.0"
android:fromYScale="0.0"
android:pivotX="50%"
android:pivotY="50%"
android:toXScale="2"
android:toYScale="2" />
>
/*
* 使用方式2:java
*/
// 步驟1:創建 需要設置動畫的 視圖View
Button mButton = (Button) findViewById(R.id.Button);
// 步驟2:創建透明度動畫的對象 & 設置動畫效果
Animation alphaAnimation = new AlphaAnimation(1,0);
// 步驟3:創建對應的插值器類對象
alphaAnimation.setDuration(3000);
Interpolator overshootInterpolator = new OvershootInterpolator();
// 步驟4:給動畫設置插值器
alphaAnimation.setInterpolator(overshootInterpolator);
// 步驟5:播放動畫
mButton.startAnimation(alphaAnimation);
- 那么使用插值器時的資源ID是什么呢?即有哪些類型的插值器可供我們使用呢?
- 插值器分為兩種:Android內置默認 & 自定義,下面我將詳細介紹
4. 系統內置插值器
4.1 類型
Android
內置了 9 種內置的插值器實現:
4.2 具體使用
- 當在XML文件設置插值器時,只需傳入對應的插值器資源ID即可
- 當在Java代碼設置插值器時,只需創建對應的插值器對象即可
系統默認的插值器是
AccelerateDecelerateInterpolator
,即先加速后減速
4.3 效果圖
- 使用
Android
內置的插值器能滿足大多數的動畫需求 - 如果上述9個插值器無法滿足需求,還可以自定義插值器
- 下面將介紹如何自定義插值器(
Interpolator
)
5. 自定義插值器
5.1 本質
根據動畫的進度(0%-100%)計算出當前屬性值改變的百分比
5.2 實現方式
自定義插值器需要實現Interpolator或TimeInterpolator接口,并復寫getInterpolation()方法
- 補間動畫 實現
Interpolator
接口;屬性動畫實現TimeInterpolator
接口TimeInterpolator
接口是屬性動畫中新增的,用于兼容Interpolator
接口,這使得所有過去的Interpolator
實現類都可以直接在屬性動畫使用
Interpolator接口和TimeInterpolator接口說明如下:
// Interpolator接口
public interface Interpolator {
// 內部只有一個方法:getInterpolation()
float getInterpolation(float input) {
// 參數說明
// input值值變化范圍是0-1,且隨著動畫進度(0% - 100% )均勻變化
// 即動畫開始時,input值 = 0;動畫結束時input = 1
// 而中間的值則是隨著動畫的進度(0% - 100%)在0到1之間均勻增加
...// 插值器的計算邏輯
return xxx;
// 返回的值就是用于估值器繼續計算的fraction值,下面會詳細說明
}
// TimeInterpolator接口
// 同上
public interface TimeInterpolator {
float getInterpolation(float input){
...
};
}
從上面可以看出,自定義插值器的關鍵在于:對input值根據動畫的進度(0%-100%)通過邏輯計算從而計算出當前屬性值改變的百分比。先來看兩個已經實現好的系統內置差值器:
- 勻速插值器:
LinearInterpolator
- 先加速再減速 插值器:
AccelerateDecelerateInterpolator
/*
* 勻速差值器:LinearInterpolator
*/
@HasNativeInterpolator
public class LinearInterpolator extends BaseInterpolator implements NativeInterpolatorFactory {
... // 僅貼出關鍵代碼
public float getInterpolation(float input) {
return input;
// 沒有對input值進行任何邏輯處理,直接返回
// 即input值 = fraction值
// 因為input值是勻速增加的,因此fraction值也是勻速增加的,所以動畫的運動情況也是勻速的,所以是勻速插值器
}
/*
* 先加速再減速 差值器:AccelerateDecelerateInterpolator
*/
@HasNativeInterpolator
public class AccelerateDecelerateInterpolator implements Interpolator, NativeInterpolatorFactory {
... // 僅貼出關鍵代碼
public float getInterpolation(float input) {
return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
// input的運算邏輯如下:
// 使用了余弦函數,因input的取值范圍是0到1,那么cos函數中的取值范圍就是π到2π。
// 而cos(π)的結果是-1,cos(2π)的結果是1
// 所以該值除以2加上0.5后,getInterpolation()方法最終返回的結果值還是在0到1之間。只不過經過了余弦運算之后,最終的結果不再是勻速增加的了,而是經歷了一個先加速后減速的過程
// 所以最終,fraction值 = 運算后的值 = 先加速后減速
// 所以該差值器是先加速再減速的
}
}
5.3 實例說明
下面,我將寫一個自定義Interpolator
:先減速后加速。
/*
* 步驟1:根據需求實現Interpolator接口
* DecelerateAccelerateInterpolator.java
*/
public class DecelerateAccelerateInterpolator implements TimeInterpolator {
@Override
public float getInterpolation(float input) {
float result;
if (input <= 0.5) {
result = (float) (Math.sin(Math.PI * input)) / 2;
// 使用正弦函數來實現先減速后加速的功能,邏輯如下:
// 因為正弦函數初始弧度變化值非常大,剛好和余弦函數是相反的
// 隨著弧度的增加,正弦函數的變化值也會逐漸變小,這樣也就實現了減速的效果。
// 當弧度大于π/2之后,整個過程相反了過來,現在正弦函數的弧度變化值非常小,漸漸隨著弧度繼續增加,變化值越來越大,弧度到π時結束,這樣從0過度到π,也就實現了先減速后加速的效果
} else {
result = (float) (2 - Math.sin(Math.PI * input)) / 2;
}
return result;
// 返回的result值 = 隨著動畫進度呈先減速后加速的變化趨勢
}
}
/*
* 步驟2:設置使用
* MainActivity.java
*/
// 1. 創建動畫作用對象:此處以Button為例
mButton = (Button) findViewById(R.id.Button);
// 2. 獲得當前按鈕的位置
float curTranslationX = mButton.getTranslationX();
// 3. 創建動畫對象 & 設置動畫
ObjectAnimator animator = ObjectAnimator.ofFloat(mButton, "translationX", curTranslationX, 300,curTranslationX);
// 表示的是:
// 動畫作用對象是mButton
// 動畫作用的對象的屬性是X軸平移
// 動畫效果是:從當前位置平移到 x=1500 再平移到初始位置
// 4. 設置步驟1中設置好的插值器:先減速后加速
animator.setInterpolator(new DecelerateAccelerateInterpolator());
// 5. 啟動動畫
animator.start();
效果圖
6. 與估值器的區別
估值器和插值器很多人容易混淆,具體區別如下:
7. 總結
- 本文對
Android
動畫中的插值器進行了詳細分析,相信通過本文你已經能實現復雜的動畫效果 - Carson帶你學
Android
動畫系列文章:
Carson帶你學Android:一份全面&詳細的動畫知識學習攻略
Carson帶你學Android:常見的三種動畫類型
Carson帶你學Android:補間動畫學習教程
Carson帶你學Android:屬性動畫學習教程
Carson帶你學Android:逐幀動畫學習教程
Carson帶你學Android:自定義動畫神器-估值器(含實例教學)
Carson帶你學Android:自定義動畫神器-插值器(含實例教學)
歡迎關注Carson_Ho的簡書
不定期分享關于安卓開發的干貨,追求短、平、快,但卻不缺深度。