android+动画队列,Android属性动画详解
前言
屬性動(dòng)畫是Android 3.0(API 11)新加入的動(dòng)畫框架,屬性動(dòng)畫彌補(bǔ)了視圖動(dòng)畫的很多短板,因此已經(jīng)成為大多數(shù)動(dòng)畫場(chǎng)景的首選框架。
目錄
目錄
1. 屬性動(dòng)畫出現(xiàn)的原因
在屬性動(dòng)畫出現(xiàn)以前,Android主要有兩種動(dòng)畫,幀動(dòng)畫(Frame Animation)和補(bǔ)間動(dòng)畫(Tween Animation),這兩種動(dòng)畫統(tǒng)稱為視圖動(dòng)畫。幀動(dòng)畫是通過逐幀播放圖片來實(shí)現(xiàn)動(dòng)畫效果,補(bǔ)間動(dòng)畫雖然提供了旋轉(zhuǎn)、縮放、位移、透明度的動(dòng)畫效果,卻有不可忽視的3大缺陷:
作用對(duì)象有限,只能作用于View及其子類
動(dòng)畫種類有限,只有旋轉(zhuǎn)、縮放、位移、透明度4種動(dòng)畫
只是改變了View的顯示效果,沒有真正改變View的屬性。例如:對(duì)
View作位移的補(bǔ)間動(dòng)畫后,View雖然顯示改變,但是響應(yīng)區(qū)域卻還在原來的位置,這在很多應(yīng)用場(chǎng)景下是不可行的。
因此,為了彌補(bǔ)視圖動(dòng)畫的不足,屬性動(dòng)畫就應(yīng)運(yùn)而生了。
2. 屬性動(dòng)畫概述
2.1 原理
屬性動(dòng)畫通過在預(yù)設(shè)的規(guī)則下不斷地改變值,并將值設(shè)置給作用對(duì)象的屬性,從而達(dá)到動(dòng)畫效果。這個(gè)規(guī)則可以由我們定制,其中有兩個(gè)重要的工具,可以幫助我們定制值的變化規(guī)則,一個(gè)是插值器(Interpolator),一個(gè)是估值器(TypeEvaluator)
2.2 插值器
插值器定義了動(dòng)畫的變化率,能幫助我們實(shí)現(xiàn)非線性改變的動(dòng)畫。Android提供了幾種插值器,如加速變化的AccelerateInterpolator,先加速后減速的AccelerateDecelerateInterpolator等等,感興趣的朋友可以自行百度查看。如果系統(tǒng)提供的插值器不能滿足我們的要求,我們還可以自定義插值器(通過下面的方式)
/**
* 自定義插值器
* 實(shí)現(xiàn)TimeInterpolator接口
*
*/
class MyInterpolator implements TimeInterpolator{
//實(shí)現(xiàn)getInterpolation方法
//此方法的參數(shù)input可理解為動(dòng)畫的進(jìn)度,值的區(qū)間是在[0,1],在此區(qū)間里隨著時(shí)間均勻地改變
//返回值是內(nèi)插值,從廣義上理解是一個(gè)時(shí)間因子,體現(xiàn)了動(dòng)畫在時(shí)間上的變化因素;從狹義上可理解為動(dòng)畫改變的百分比
@Override
public float getInterpolation(float input) {
return 0;
}
}
2.3 估值器
估值器的作用是根據(jù)開始值、結(jié)束值、開始結(jié)束之間的一個(gè)比例來計(jì)算出最終的值。在屬性動(dòng)畫上則是計(jì)算出動(dòng)畫對(duì)應(yīng)的最終的屬性值。系統(tǒng)默認(rèn)提供了3種估值器
IntEvaluator整型估值器,值的類型為整型
FloatEvaluator浮點(diǎn)型估值器,值的類型為浮點(diǎn)型
ArgbEvaluator,值的類型為ARGB值,可以用來計(jì)算顏色值
如果系統(tǒng)提供的估值器不能滿足我們的要求,我們還可以自定義估值器
/**
* 自定義估值器
* 實(shí)現(xiàn)TypeEvaluator接口
*/
class MyEvaluator implements TypeEvaluator{
/**
*
* @param fraction 開始過渡到結(jié)束之間的一個(gè)比例
* @param startValue 開始值
* @param endValue 結(jié)束值
* @return 開始過渡到結(jié)束的具體值
*/
@Override
public T evaluate(float fraction, T startValue, T endValue) {
return null;
}
}
3. 屬性動(dòng)畫的使用
屬性動(dòng)畫主要通過兩個(gè)類來使用,ValueAnimator和ObjectAnimator,這兩個(gè)的區(qū)別主要是ValueAnimator只是計(jì)算值,賦值給對(duì)象屬性需要我們手動(dòng)監(jiān)聽值的變化來進(jìn)行;ObjectAnimator則對(duì)賦值屬性這一步封裝進(jìn)了內(nèi)部,也就是自動(dòng)賦值。
3.1 ValueAnimator
3.1.1 創(chuàng)建ValueAnimator
創(chuàng)建ValueAnimator可以在代碼里面創(chuàng)建、設(shè)置,也可以在xml里面創(chuàng)建、設(shè)置
xml創(chuàng)建
在res目錄里創(chuàng)建animator目錄,之后創(chuàng)建Animator resources file,ValueAnimator在xml文件的根結(jié)點(diǎn)是animator,例如:
android:valueFrom="30"
android:valueTo="60"
android:duration="2000"
android:valueType="intType" //選擇值的類型
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:repeatMode="reverse"
android:repeatCount="1">
之后直接在代碼里面加載剛才的資源文件就可以了
ValueAnimator valueAnimator= (ValueAnimator) AnimatorInflater.loadAnimator(this,R.animator.textsize_animator);
代碼里創(chuàng)建
雖然ValueAnimator提供了公共的無參的構(gòu)造方法,但是官方建議我們使用其工廠方法來創(chuàng)建ValueAnimator
(1)ValueAnimator.ofInt(int... values)
使用這種方式創(chuàng)建ValueAnimator,值的類型是int,會(huì)默認(rèn)使用整形估值器。
(2)ValueAnimator.ofFloat(float... values)
對(duì)應(yīng)值的類型是float,會(huì)默認(rèn)使用浮點(diǎn)型估值器
(3)ValueAnimator.ofArgb(int... values)
對(duì)應(yīng)值的類型是代表顏色的32位的int,會(huì)默認(rèn)使用ArgbEvaluator估值器
(4)ValueAnimator.ofObject(TypeEvaluator evaluator,Object... values)
對(duì)應(yīng)值的類型是Object,這種方式需要顯式傳入估值器,因?yàn)閷?duì)于Object類型沒有系統(tǒng)提供的估值器,也不可能提供估值器,因?yàn)閷?duì)于不同的對(duì)象其計(jì)算方式不同
3.1.2 設(shè)置ValueAnimator
ValueAnimator提供了方法設(shè)置其動(dòng)畫的相關(guān)的屬性,具體如下
valueAnimator.setDuration(2000);//設(shè)置動(dòng)畫持續(xù)時(shí)間,以毫秒為單位
valueAnimator.setInterpolator(new DecelerateInterpolator());//設(shè)置插值器
valueAnimator.setRepeatMode(ValueAnimator.REVERSE);//設(shè)置動(dòng)畫重復(fù)模式,RESTART表示動(dòng)畫正序重復(fù),REVERSE代表倒序重復(fù)
valueAnimator.setRepeatCount(1);//設(shè)置重復(fù)次數(shù),也就是動(dòng)畫播放次數(shù)=RepeatCount+1,ValueAnimator.INFINITE表示無限重復(fù)
valueAnimator.setStartDelay(1000);//設(shè)置動(dòng)畫延遲播放的時(shí)間
3.1.3 監(jiān)聽動(dòng)畫值
ValueAnimator提供了回調(diào)以監(jiān)聽動(dòng)畫值,我們可以在此回調(diào)中拿到屬性值并手動(dòng)賦值給對(duì)象屬性,從而達(dá)到效果,需要注意的是,對(duì)象是View的時(shí)候,有時(shí)需要我們?cè)谫x值屬性后調(diào)用View.invalidate()或者View.requestLayout()方法來刷新界面實(shí)現(xiàn)視覺效果
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {//動(dòng)畫值更新時(shí)的監(jiān)聽器
@Override
public void onAnimationUpdate(ValueAnimator animation) {//動(dòng)畫更新時(shí)會(huì)回調(diào)此方法
Float value= (Float) animation.getAnimatedValue();//拿到更新后動(dòng)畫值
tvAnimator.setTextSize(value);//手動(dòng)將動(dòng)畫值賦值給對(duì)象
}
});
3.2 ObjectAnimator
ObjectAnimator利用反射調(diào)用對(duì)象屬性的set方法從而自動(dòng)賦值給對(duì)象屬性完成動(dòng)畫,也就是說ObjectAnimator作用的對(duì)象必須提供該屬性的set方法(如果沒有提供初始值,還必須提供get方法)需要注意的是,set和get方法名必須滿足如下規(guī)則
set/get+屬性名(屬性名頭字母大寫)
3.2.1 創(chuàng)建ObjectAnimator
xml創(chuàng)建
在res/animator目錄下創(chuàng)建animator的xml文件,根結(jié)點(diǎn)為objectAnimator
android:valueType="floatType"
android:valueTo="200.0"
android:valueFrom="100.0"
android:interpolator="@android:anim/accelerate_decelerate_interpolator"
android:propertyName="width"
/>
在代碼里加載xml創(chuàng)建的ObjectAnimator并設(shè)置作用對(duì)象
ObjectAnimator objectAnimator= (ObjectAnimator) AnimatorInflater.loadAnimator(this,R.animator.test);//加載xml中的動(dòng)畫
objectAnimator.setTarget(tvAnimator);//設(shè)置作用對(duì)象
代碼里創(chuàng)建
和ValueAnimator的方式差不多,這里以ofInt為例說明創(chuàng)建方式,其他的可以類推。
/*
1. 參數(shù)解釋
target:ObjectAnimator作用的對(duì)象
propertyName:屬性名
values:過渡值(開始值、結(jié)束值)
*/
ObjectAnimator objectAnimator=ObjectAnimator.ofInt(Object target,String propertyName,int... values);
3.2.2 設(shè)置ObjectAnimator
同ValueAnimator設(shè)置方式一樣,不再贅述。
3.3 AnimatorSet(組合動(dòng)畫)
AnimatorSet用于把很多動(dòng)畫按照一定順序組合起來播放,AnimatorSet采用了構(gòu)造器模式來組合動(dòng)畫
public Builder play(Animator anim) {
if (anim != null) {
return new Builder(anim);
}
return null;
}
//play函數(shù)會(huì)生成構(gòu)造器并將該動(dòng)畫加入到播放隊(duì)列中
play函數(shù)是AnimatorSet中唯一可以創(chuàng)建構(gòu)造器的函數(shù),此外構(gòu)造器還提供了多種方法組合動(dòng)畫,這些方法都是以play函數(shù)傳入的Animator作為基準(zhǔn)來構(gòu)建播放順序的,例如:
//將animator1和animator2一起播放
animatorSet.play(animator1).with(animator2);
//將animator1插入animator2之后播放
animatorSet.play(animator1).after(animator2);
//將animator1插入animator2之前播放
animatorSet.play(animator1).before(animator2);
AnimatorSet本身還提供了兩個(gè)方法來添加動(dòng)畫,
public void playSequentially(Animator... items)//一個(gè)接一個(gè)地先后播放動(dòng)畫組,前面的動(dòng)畫先播放
public void playTogether(Animator... items)//同時(shí)播放動(dòng)畫組
這兩個(gè)方法本質(zhì)上也是采用了構(gòu)造器的after、before和with方法來構(gòu)建動(dòng)畫的播放順序。
3.4 監(jiān)聽動(dòng)畫
Animator類允許對(duì)動(dòng)畫開始、結(jié)束、取消、重復(fù)和暫停等時(shí)刻進(jìn)行監(jiān)聽
animator.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
}
@Override
public void onAnimationCancel(Animator animation) {
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
animator.addPauseListener(new Animator.AnimatorPauseListener() {
@Override
public void onAnimationPause(Animator animation) {
}
@Override
public void onAnimationResume(Animator animation) {
}
});
如果只想監(jiān)聽其中的幾個(gè)方法,可以采用AnimatorListenerAdapter
animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
}
});
animator.addPauseListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationPause(Animator animation) {
}
});
參考和擴(kuò)展
總結(jié)
以上是生活随笔為你收集整理的android+动画队列,Android属性动画详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux下apk包名查看,使用adb命
- 下一篇: android软件更新模块实现的技术和方