Android動(dòng)畫(huà)系列之屬性動(dòng)畫(huà)的基本使用教程
前言
屬性動(dòng)畫(huà)相較幀動(dòng)畫(huà)和補(bǔ)間動(dòng)畫(huà)更強(qiáng)大,幀動(dòng)畫(huà)和補(bǔ)間動(dòng)畫(huà)只能應(yīng)用于 View 及其子類(lèi),而屬性動(dòng)畫(huà)可以修改任何對(duì)象的屬性值,屬性值可在指定的一段時(shí)間內(nèi)自動(dòng)改變,根據(jù)對(duì)象屬性值的變化進(jìn)而實(shí)現(xiàn)更復(fù)雜的動(dòng)畫(huà)。
- 屬性動(dòng)畫(huà)的常用設(shè)置
- ValueAnimator
- ObjectAnimator
- 關(guān)鍵幀
- 插值器和估值器
屬性動(dòng)畫(huà)的常用設(shè)置
下面是屬性動(dòng)畫(huà)的常用設(shè)置,具體如下:
//設(shè)置屬性動(dòng)畫(huà)持續(xù)時(shí)間
animator.setDuration(2000);
//設(shè)置屬性插值器
animator.setInterpolator(new AccelerateInterpolator());
//設(shè)置屬性動(dòng)畫(huà)重復(fù)播放模式
animator.setRepeatMode(ValueAnimator.REVERSE);
//設(shè)置屬性動(dòng)畫(huà)重復(fù)播放次數(shù)
animator.setRepeatCount(0);
//設(shè)置屬性動(dòng)畫(huà)延時(shí)播放的時(shí)間
animator.setStartDelay(0);
//設(shè)置屬性動(dòng)畫(huà)估值器,用于控制最終屬性值(API22)
animator.setCurrentFraction(0.5f);
//設(shè)置當(dāng)前播放時(shí)間,其值在Duration范圍之內(nèi)
animator.setCurrentPlayTime(1000);
//設(shè)置屬性動(dòng)畫(huà)估值器,用于控制最終屬性值
animator.setEvaluator(new IntEvaluator());
//設(shè)置屬性動(dòng)畫(huà)監(jiān)聽(tīng)
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i(TAG, animation.getAnimatedValue() + "");
//
}
});
//...
ValueAnimator
ValueAnimator 提供了一個(gè)簡(jiǎn)單的計(jì)時(shí)引擎,用于執(zhí)行動(dòng)畫(huà)時(shí)根據(jù)設(shè)置的時(shí)長(zhǎng)以及其他屬相完成動(dòng)畫(huà)值的計(jì)算,然后就可以將動(dòng)畫(huà)值設(shè)置到合適的目標(biāo)對(duì)象上,使用的插值器默認(rèn)時(shí) AccelerateDecelerateInterpolator,表示動(dòng)畫(huà)開(kāi)始和結(jié)束時(shí)較慢,中間加速完成動(dòng)畫(huà),下面是源碼中默認(rèn)的插值器,具體如下:
// The time interpolator to be used if none is set on the animation
private static final TimeInterpolator sDefaultInterpolator =
new AccelerateDecelerateInterpolator();
在 ValueAnimator 中已經(jīng)內(nèi)部處理了一些估值器 IntEvaluator 和 FloatEvaluator,也就是說(shuō)如果使用的時(shí) ofInt 和 ofFloat 方法作為動(dòng)畫(huà)的屬性值,那么 ValueAnimator 會(huì)自動(dòng)處理 int 和 float 值的變化,在源碼中找了一下,這部分內(nèi)容在 PropertyValuesHolder 這個(gè)類(lèi)中,具體如下:
void init() {
if (mEvaluator == null) {
// We already handle int and float automatically, but not their Object
// equivalents
mEvaluator = (mValueType == Integer.class) ? sIntEvaluator :
(mValueType == Float.class) ? sFloatEvaluator :
null;
}
if (mEvaluator != null) {
// KeyframeSet knows how to evaluate the common types - only give it a custom
// evaluator if one has been set on this class
mKeyframes.setEvaluator(mEvaluator);
}
}
ValueAnimator 可以使用代碼創(chuàng)建,也可以使用 xml 創(chuàng)建,下面以平移動(dòng)畫(huà)為例說(shuō)明 ValueAnimator 的使用方式,其他如縮放、旋轉(zhuǎn)等使用方式類(lèi)似。
使用代碼創(chuàng)建
private void translation(){
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 100);
valueAnimator.setDuration(2000);
valueAnimator.setInterpolator(new AccelerateInterpolator());
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
valueAnimator.setRepeatCount(0);
valueAnimator.setStartDelay(0);
// valueAnimator.setCurrentFraction(0.5f);
// valueAnimator.setCurrentPlayTime(1000);
valueAnimator.setEvaluator(new IntEvaluator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i(TAG, animation.getAnimatedValue() + "");
int x = (int) animation.getAnimatedValue();
ivImage.setTranslationX(x);
ivImage.setTranslationY(x);
}
});
valueAnimator.start();
}
使用xml創(chuàng)建
在 res/animator 文件夾下創(chuàng)建 test_animator.xml 文件,文件內(nèi)容如下:
<?xml version="1.0" encoding="utf-8"?> <animator xmlns:android="http://schemas.android.com/apk/res/android" android:valueFrom="0" android:valueTo="100" android:valueType="intType" android:duration="2000" android:startOffset ="0" android:repeatMode = "reverse" android:repeatCount = "0" android:interpolator = "@android:anim/accelerate_interpolator"> </animator>
然后在 Activity 中獲取 ValueAnimator,設(shè)置目標(biāo)對(duì)象,啟動(dòng)動(dòng)畫(huà)即可,具體如下:
private void translation(){
ValueAnimator animator = (ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.test_animator);
animator.setTarget(ivImage);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i(TAG, animation.getAnimatedValue() + "");
int x = (int) animation.getAnimatedValue();
ivImage.setTranslationX(x);
ivImage.setTranslationY(x);
}
});
}
測(cè)試效果
這里使用 ValueAnimator 來(lái)實(shí)現(xiàn)平移動(dòng)畫(huà),測(cè)試效果如下:

ObjectAnimator
ObjectAnimator 是 ValueAnimator 的子類(lèi),可在目標(biāo)對(duì)象上支持動(dòng)畫(huà)屬性的設(shè)置,在其構(gòu)造方法中通過(guò)參數(shù)指定目標(biāo)對(duì)象以及所對(duì)應(yīng)動(dòng)畫(huà)屬性的名稱(chēng),然后會(huì)相應(yīng)的執(zhí)行對(duì)應(yīng)的動(dòng)畫(huà)屬性的 setter 方法來(lái)最終完成動(dòng)畫(huà)的執(zhí)行,也就是說(shuō)屬性動(dòng)畫(huà) ObjectAnimator 最終調(diào)用目標(biāo)對(duì)象的 setter 方法完成目標(biāo)對(duì)象屬性值的變化,然后相應(yīng)的改變目標(biāo)對(duì)象的屬性,從而實(shí)現(xiàn)目標(biāo)對(duì)象的動(dòng)畫(huà)效果,下面以透明度變化來(lái)介紹 ObjectAnimator 的基本使用,代碼參考如下:
private void alpha(){
ObjectAnimator animator = ObjectAnimator.ofFloat(ivImage,"alpha",1f,0,1f);
animator.setDuration(3000);
//其他屬性動(dòng)畫(huà)設(shè)置
//...
animator.start();
}
下面是測(cè)試效果,如下圖所示:

至于平移、旋轉(zhuǎn)、縮放動(dòng)畫(huà)實(shí)現(xiàn)方式基本如上,這里不再贅述,其對(duì)應(yīng)的 setter 方法對(duì)應(yīng)關(guān)系如下:
| 屬性 | 作用 | 對(duì)應(yīng)方法 |
|---|---|---|
| Alpha | 控制View的透明度 | setAlpha |
| TranslationX | 控制X方向的位移 | setTranslationX |
| TranslationY | 控制Y方向的位移 | setTranslationY |
| ScaleX | 控制X方向的縮放倍數(shù) | setScaleX |
| ScaleY | 控制Y方向的縮放倍數(shù) | setScaleY |
| Rotation | 控制以屏幕方向?yàn)檩S的旋轉(zhuǎn)度數(shù) | setRotation |
| RotationX | 控制以X軸為軸的旋轉(zhuǎn)度數(shù) | setRotationX |
| RotationY | 控制以Y軸為軸的旋轉(zhuǎn)度數(shù) | setRotationY |
ObjectAnimator 提供了很多的 ofXxx() 方法來(lái)方面設(shè)置屬性動(dòng)畫(huà),如下圖所示:

可根據(jù)不同的動(dòng)畫(huà)需求使用 ObjectValueAnimator 不同 ofXxx() 方法來(lái)實(shí)現(xiàn)相應(yīng)的動(dòng)畫(huà)。
關(guān)鍵幀
這里簡(jiǎn)單說(shuō)一下關(guān)鍵幀的使用,顧名思義關(guān)鍵幀就是在某個(gè)固定時(shí)刻上定義具體的屬性值,為定義的將按照估值器返回的值返回屬性值,屬性動(dòng)畫(huà)中的關(guān)鍵幀使用方式如下:
/**
* 關(guān)鍵幀的使用
*/
private void keyFrame(){
Keyframe keyframe1 = Keyframe.ofFloat(0,0);
Keyframe keyframe2 = Keyframe.ofFloat(0.25f,300);
//每個(gè)KeyFrame可設(shè)置自己的插值器
keyframe2.setInterpolator(new AccelerateInterpolator());
Keyframe keyframe3 = Keyframe.ofFloat(0.75f,100);
Keyframe keyframe4 = Keyframe.ofFloat(1,400);
PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX",keyframe1,keyframe2,keyframe3,keyframe4);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(ivImage,holder);
animator.setDuration(3000);
animator.start();
}
看一下添加關(guān)鍵幀之后對(duì)普通平移動(dòng)畫(huà)的改變,實(shí)現(xiàn)測(cè)試效果如下:

插值器和估值器
插值器(TimeInterpolator) 表示的是整個(gè)動(dòng)畫(huà)期間動(dòng)畫(huà)的變化規(guī)律,如加速、減速等。
Android 內(nèi)置許多插值器,這些插值器基本涵蓋了實(shí)際開(kāi)發(fā)中的大部分情況,具體如下:

如果內(nèi)置的插值器不滿(mǎn)足需求,也可以自定義插值器。
估值器(TypeEvaluator)表示的是在整個(gè)動(dòng)畫(huà)期間各時(shí)刻屬性值的具體變化。
這里自定義一個(gè)估值器來(lái)實(shí)現(xiàn)一個(gè) View 沿正弦曲線(xiàn)運(yùn)動(dòng),自定義估值器如下:
/**
* 自定義估值器
* Point封裝了坐標(biāo)x和y
*/
public class SineTypeValue implements TypeEvaluator<Point> {
@Override
public Point evaluate(float fraction, Point startValue, Point endValue) {
//y = sinA
float distance = fraction * (endValue.getX() - startValue.getX());
float x = startValue.getX() + distance;
float y = startValue.getY() + (float) Math.sin(distance / 100 * Math.PI) * 100;
Point point = new Point();
point.setX(x);
point.setY(y);
return point;
}
}
然后給動(dòng)畫(huà)設(shè)置該估值器,監(jiān)聽(tīng)動(dòng)畫(huà)屬性設(shè)置 View 的位置即可實(shí)現(xiàn)一個(gè) View 沿正弦曲線(xiàn)運(yùn)動(dòng),使用方式如下:
/**
* 自定義估值器的使用
* 正弦運(yùn)動(dòng)的估值器
*/
private void sina(){
Point startPoint = new Point(ivImage.getX(),ivImage.getY());
Point endPoint = new Point(ivImage.getX()+500,ivImage.getY());
ValueAnimator valueAnimator = ValueAnimator.ofObject(new SineTypeValue(), startPoint, endPoint);
valueAnimator.setDuration(5000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
Log.i(TAG, animation.getAnimatedValue() + "");
Point point = (Point) animation.getAnimatedValue();
ivImage.setX(point.getX());
ivImage.setY(point.getY());
}
});
valueAnimator.start();
}
測(cè)試效果如下:

自定義估值器
到此這篇關(guān)于Android動(dòng)畫(huà)系列之屬性動(dòng)畫(huà)基本使用的文章就介紹到這了,更多相關(guān)Android屬性動(dòng)畫(huà)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Android屬性動(dòng)畫(huà)實(shí)現(xiàn)圖片從左到右逐漸消失
- Android動(dòng)畫(huà)教程之屬性動(dòng)畫(huà)詳解
- Android利用屬性動(dòng)畫(huà)實(shí)現(xiàn)優(yōu)酷菜單
- Android屬性動(dòng)畫(huà)特點(diǎn)詳解
- Android使用屬性動(dòng)畫(huà)如何自定義倒計(jì)時(shí)控件詳解
- Android屬性動(dòng)畫(huà)之ValueAnimator代碼詳解
- Android 屬性動(dòng)畫(huà)ValueAnimator與插值器詳解
- Android源碼解析之屬性動(dòng)畫(huà)詳解
- Android深入分析屬性動(dòng)畫(huà)源碼
相關(guān)文章
簡(jiǎn)單談?wù)凙ndroid中SP與DP的區(qū)別
Android里面的sp和dp網(wǎng)上有很多文章都談過(guò)了,但是看后總有一種意猶未盡的感覺(jué)。現(xiàn)在我也來(lái)談?wù)刣p和sp,和大家交流一下,不對(duì)之處歡迎拍磚。2016-09-09
Android實(shí)現(xiàn)懸浮可拖拽的Button
這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)懸浮可拖拽的Button,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-06-06
Android開(kāi)發(fā)之OkHttpUtils的具體使用方法
這篇文章主要介紹了Android開(kāi)發(fā)之OkHttpUtils的具體使用方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-08-08
Android 快速繪制一個(gè)圓角矩形的實(shí)例
下面小編就為大家分享一篇Android 快速繪制一個(gè)圓角矩形的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
Android自定義Dialog實(shí)現(xiàn)加載對(duì)話(huà)框效果
這篇文章將介紹如何定制當(dāng)今主流的對(duì)話(huà)框,通過(guò)自定義dialog實(shí)現(xiàn)加載對(duì)話(huà)框效果,具體實(shí)現(xiàn)代碼大家通過(guò)本文學(xué)習(xí)吧2018-05-05
Android編程實(shí)現(xiàn)自定義輸入法功能示例【輸入密碼時(shí)防止第三方竊取】
這篇文章主要介紹了Android編程實(shí)現(xiàn)自定義輸入法功能,可實(shí)習(xí)輸入密碼時(shí)防止第三方竊取的效果,結(jié)合實(shí)例形式詳細(xì)分析了Android布局、控件及輸入法相關(guān)操作技巧,需要的朋友可以參考下2017-01-01
Android apk無(wú)法安裝及閃退問(wèn)題解決辦法
這篇文章主要介紹了Android apk無(wú)法安裝及閃退問(wèn)題的相關(guān)資料,這里對(duì)閃退問(wèn)題進(jìn)行詳解及解決步驟的詳細(xì)介紹,需要的朋友可以參考下2017-07-07
關(guān)于Android實(shí)現(xiàn)簡(jiǎn)單的微信朋友圈分享功能
這篇文章主要介紹了關(guān)于Android實(shí)現(xiàn)簡(jiǎn)單的微信朋友圈分享功能,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下2017-02-02
flutter封裝點(diǎn)擊菜單工具欄組件checkBox多選版
這篇文章主要為大家介紹了flutter封裝一個(gè)點(diǎn)擊菜單工具欄組件,checkBox多選版的示例示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05

