1睡陪、視圖動(dòng)畫Animation (Tween Animation)
通過不斷的對(duì)view對(duì)象做圖像變換(漸變寺渗、平移匿情、縮放、旋轉(zhuǎn))而產(chǎn)生動(dòng)畫效果信殊,這種動(dòng)畫只適用于View對(duì)象炬称。
1、AlphaAnimation
AlphaAnimation(float fromAlpha, float toAlpha)
其中涡拘,1:不透明玲躯;0:透明
2、RotateAnimation
RotateAnimation(float fromDegrees, float toDegrees)
---
RotateAnimation(float fromDegrees, float toDegrees, float pivotX, float pivotY)
---
RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
注意:
- 旋轉(zhuǎn)的中心點(diǎn)鳄乏,默認(rèn)是view的左上角跷车;
- pivotX、pivotY汞窗,是旋轉(zhuǎn)的中心點(diǎn)的偏移量姓赤;
- pivotXType的取值可以是RELATIVE_TO_PARENT、RELATIVE_TO_SELF仲吏,代表的是中心點(diǎn)(默認(rèn)是view的左上角)偏移量大小的取值是相對(duì)于自身還是相對(duì)于parent不铆,最終都是相對(duì)于view的左上角進(jìn)行偏移。
即旋轉(zhuǎn)中心點(diǎn)從view的左上角裹唆,偏移到了右下角(相對(duì)于parent50%的地方)
3誓斥、TranslateAnimation
TranslateAnimation(float fromXDelta, float toXDelta, float fromYDelta, float toYDelta)
---
TranslateAnimation(int fromXType, float fromXValue, int toXType, float toXValue,
int fromYType, float fromYValue, int toYType, float toYValue)
4、ScaleAnimation
ScaleAnimation(float fromX, float toX, float fromY, float toY)
---
ScaleAnimation(float fromX, float toX, float fromY, float toY,
float pivotX, float pivotY)
---
ScaleAnimation(float fromX, float toX, float fromY, float toY,
int pivotXType, float pivotXValue, int pivotYType, float pivotYValue)
相對(duì)于某個(gè)中心點(diǎn)縮放许帐,和RotateAnimation類似
代碼如下:
//透明動(dòng)畫效果
AlphaAnimation alphaAnimation=new AlphaAnimation(0,1);
alphaAnimation.setDuration(1000);
view.startAnimation(alphaAnimation);
---
//旋轉(zhuǎn)動(dòng)畫效果
RotateAnimation rotateAnimation=new RotateAnimation(0,360,RotateAnimation.RELATIVE_TO_PARENT,0.1f,
RotateAnimation.RELATIVE_TO_PARENT,0.1f);
rotateAnimation.setDuration(1000);
v.startAnimation(rotateAnimation);
---
//平移動(dòng)畫效果
TranslateAnimation translateAnimation=new TranslateAnimation(TranslateAnimation.RELATIVE_TO_PARENT,0,
TranslateAnimation.RELATIVE_TO_PARENT,0.2f,
TranslateAnimation.RELATIVE_TO_PARENT,0,
TranslateAnimation.RELATIVE_TO_PARENT,0.2f);
translateAnimation.setDuration(1000);
v.startAnimation(translateAnimation);
---
//縮放動(dòng)畫效果
ScaleAnimation scaleAnimation=new ScaleAnimation(1,0,1,0,ScaleAnimation.RELATIVE_TO_PARENT,0.2f,
ScaleAnimation.RELATIVE_TO_PARENT,0.2f);
scaleAnimation.setDuration(2000);
v.startAnimation(scaleAnimation);
---
v.startAnimation(AnimationUtils.loadAnimation(this,R.anim.rotate));
//透明動(dòng)畫效果
<alpha android:duration="1000"
android:fromAlpha="1"
android:toAlpha="0"/>
---
//旋轉(zhuǎn)動(dòng)畫效果
<rotate android:duration="1000"
android:fromDegrees="0"
android:toDegrees="360"
android:repeatCount="infinite"
android:repeatMode="reverse"
android:pivotX="50%"
android:pivotY="50%"/>
---
//平移動(dòng)畫效果
<translate android:duration="1000"
android:fromXDelta="0"
android:toXDelta="20%p"
android:fromYDelta="0"
android:toYDelta="30%p"/>
注意:
- num%劳坑、num%p表示相對(duì)于自身或者父控件,跟RELATIVE_TO_PARENT成畦、RELATIVE_TO_SELF效果類似距芬;如果以浮點(diǎn)數(shù)字表示,是一個(gè)絕對(duì)值循帐,代表相對(duì)自身原始位置的像素值框仔;
- RepeatMode:
Animation.RESTART,表示動(dòng)畫重新從頭開始執(zhí)行拄养,當(dāng)一次動(dòng)畫執(zhí)行結(jié)束之后离斩,圖片將重新從頭開始執(zhí)行。
Animation.REVERSE瘪匿,表示動(dòng)畫反方向執(zhí)行跛梗,當(dāng)一次動(dòng)畫執(zhí)行結(jié)束之后,圖片將向反方向運(yùn)動(dòng)棋弥。 - RepeatCount:動(dòng)畫的重復(fù)次數(shù)核偿,Animation.INFINITE 無限循環(huán)
- fillBefore:動(dòng)畫結(jié)束時(shí)畫面停留在此動(dòng)畫的第一幀
fillAfter:動(dòng)畫結(jié)束是畫面停留在此動(dòng)畫的最后一幀 - 加載xml文件中的動(dòng)畫
AnimationUtils類調(diào)用loadAnimation(context, id)方法來加載xml文件
5、可以通過AnimationSet顽染,將動(dòng)畫以組合的形式展示
AnimationSet animationSet=new AnimationSet(true);
animationSet.setDuration(2000);
ScaleAnimation scaleAnimation=new ScaleAnimation(1,0,1,0,ScaleAnimation.RELATIVE_TO_PARENT,0.2f,
ScaleAnimation.RELATIVE_TO_PARENT,0.2f);
scaleAnimation.setDuration(2000);
animationSet.addAnimation(scaleAnimation);
...
v.startAnimation(animationSet);
6宪祥、自定義動(dòng)畫
實(shí)現(xiàn)Animation 接口的applyTransformation()方法聂薪,還可以覆蓋initialize()方法,做一些初始化的操作
public class ReversalAnimation extends Animation {
private int height;
private int width;
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
setDuration(1000);
setInterpolator(new CycleInterpolator(0.25f));
this.height = height * 2;
this.width = width;
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
Matrix matrix = t.getMatrix();
matrix.preScale(1 - (float) Math.sin((interpolatedTime) * Math.PI), 1, width / 2, 0);
matrix.preTranslate(0, -(float) Math.sin(interpolatedTime * Math.PI) * height);
}
}
其中interpolatedTime的取值為0~1蝗羊,0標(biāo)識(shí)動(dòng)畫開始執(zhí)行藏澳,1標(biāo)識(shí)動(dòng)畫執(zhí)行完了
Transformation,可以通過它獲得當(dāng)前矩陣對(duì)象matrix耀找,通過matrix將動(dòng)畫效果執(zhí)行出來
7翔悠、插值器
如下
8、監(jiān)聽器
可以設(shè)置AnimationListener野芒,獲取動(dòng)畫開始蓄愁、結(jié)束、重復(fù)事件
translateAnimation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
Toast.makeText(Main2Activity.this,"onAnimationStart",Toast.LENGTH_SHORT).show();
}
@Override
public void onAnimationEnd(Animation animation) {
Toast.makeText(Main2Activity.this,"onAnimationEnd",Toast.LENGTH_SHORT).show();
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
9狞悲、執(zhí)行動(dòng)畫
通過view的startAnimation
但是視圖動(dòng)畫不具備交互性撮抓,在縮放和平移一個(gè)View的時(shí)候,并沒有改變控件內(nèi)部的屬性值摇锋,它的有效點(diǎn)擊區(qū)域丹拯,依然保持原來的大小和位置,如圖在動(dòng)畫的結(jié)束位置點(diǎn)擊荸恕,是沒有效果的乖酬,只有在原始位置(矩形區(qū)域),點(diǎn)擊才有效果
參考:Android 動(dòng)畫學(xué)習(xí) View Animation
2融求、屬性動(dòng)畫Animator
在Android3.0(level 11)引入的咬像,通過動(dòng)態(tài)地改變對(duì)象的屬性值而達(dá)到動(dòng)畫效果缘厢,可以為任何的對(duì)象添加動(dòng)畫(當(dāng)然也包括View在內(nèi))征候。
屬性動(dòng)畫改變了View的屬性,比如對(duì)于View的最終位置x=left+translationX棍弄,所以在最終位置就可以響應(yīng)點(diǎn)擊事件陷舅;
1倒彰、ValueAnimator
ValueAnimator本身不提供任何的動(dòng)畫效果,它可以產(chǎn)生有一定規(guī)律的數(shù)字蔑赘,可以在AnimatorUpdateListener中監(jiān)聽這些數(shù)字的變化狸驳,從而完成動(dòng)畫效果
ValueAnimator動(dòng)畫的整個(gè)過程如下:
(0)预明、 ofInt(0,400)表示指定動(dòng)畫的數(shù)字區(qū)間缩赛,是從0運(yùn)動(dòng)到400;
(1)撰糠、 在動(dòng)畫過程中酥馍, Animator會(huì)根據(jù)動(dòng)畫總時(shí)間和已進(jìn)行的時(shí)間自動(dòng)計(jì)算出一個(gè)時(shí)間比例因子,大小介于0和1之間阅酪,0表示開始旨袒。
時(shí)間比例因子 = 當(dāng)前已進(jìn)行的時(shí)間/動(dòng)畫執(zhí)行的總時(shí)間
(2)汁针、Interpolator(差值器/加速器):Animator會(huì)根據(jù)時(shí)間比例因子,返回當(dāng)前動(dòng)畫進(jìn)度所對(duì)應(yīng)的數(shù)字進(jìn)度:這個(gè)數(shù)字進(jìn)度是百分制的砚尽,以小數(shù)表示施无。
publicinterfaceTimeInterpolator{
floatgetInterpolation(floatinput);
}
但是我們通過監(jiān)聽器拿到的是當(dāng)前動(dòng)畫所對(duì)應(yīng)的具體數(shù)值,而不是百分制的進(jìn)度必孤。那么就必須有一個(gè)地方會(huì)根據(jù)當(dāng)前的數(shù)字進(jìn)度猾骡,將其轉(zhuǎn)化為對(duì)應(yīng)的數(shù)值,這個(gè)地方就是Evaluator敷搪;
(3)兴想、 Evaluator:Evaluator將從加速器返回的數(shù)字進(jìn)度轉(zhuǎn)成對(duì)應(yīng)的數(shù)字值。
publicinterfaceTypeEvaluator<T>{
T evaluate(floatfraction,T startValue,T endValue)
}
(4)赡勘、 監(jiān)聽器:通過在AnimatorUpdateListener監(jiān)聽器使用animation.getAnimatedValue()函數(shù)拿到Evaluator中返回的數(shù)字值嫂便,為需要執(zhí)行動(dòng)畫的對(duì)象設(shè)置對(duì)應(yīng)屬性的屬性值。onAnimationUpdate()在動(dòng)畫每播放一幀時(shí)都會(huì)調(diào)用闸与。
動(dòng)畫在的整個(gè)過程中毙替,會(huì)根據(jù)我們當(dāng)初設(shè)置的TimeInterpolator 和TypeEvaluator的計(jì)算方式計(jì)算出的不同的屬性值,從而不斷地改變對(duì)象屬性值的大小几迄,進(jìn)而產(chǎn)生各式各樣的動(dòng)畫效果蔚龙。
創(chuàng)建ValueAnimator的常用方法如下:
- ValueAnimator ofInt(int... values)
- ValueAnimator ofArgb(int... values)
- ValueAnimator ofFloat(float... values)
- ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values)
這些方法都有默認(rèn)的加速器和Evaluator,不指定則使用默認(rèn)的映胁;
其中ofInt()的默認(rèn)Evaluator是IntEvaluator木羹,ofFloat是FloatEvalutor,ofArgb是ArgbEvaluator解孙;
參數(shù)的類型是定值
代碼如下:
ValueAnimator valueAnimator=ValueAnimator.ofFloat(0,1);
valueAnimator.setTarget(v);
valueAnimator.setDuration(1000);
valueAnimator.start();
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
float timeAnim= (float) animation.getAnimatedValue();
if(timeAnim<0.4f){
imageView.setTranslationY(-1000*timeAnim);
}else if(timeAnim>=0.4f && timeAnim<=0.8f){
imageView.setScaleX((float) Math.abs((timeAnim-0.6)/0.2));
}else {
imageView.setTranslationY(-1000*(1-timeAnim));
}
}
});
- ValueAnimator ofObject(TypeEvaluator evaluator, Object... values)
ofInt()只能傳入Integer類型的值坑填,而ofFloat()只能傳入Float類型的值。如果我們需要操作其它類型的變量弛姜,可以使用以上方法
TypeEvaluator
public class PointXYEvaluator implements TypeEvaluator<PointXY> {
@Override
public PointXY evaluate(float fraction, PointXY startValue, PointXY endValue) {
int pointX= (int) (startValue.getPointX()+(endValue.getPointX()-startValue.getPointX())*fraction);
int pointy= (int) (startValue.getPointY()+(endValue.getPointY()-startValue.getPointY())*fraction);
return new PointXY(pointX,pointy);
}
}
自定義參數(shù)類型
public class PointXY {
private int pointX;
private int pointY;
public PointXY(int pointX, int pointY) {
this.pointX = pointX;
this.pointY = pointY;
}
public int getPointX() {
return pointX;
}
public void setPointX(int pointX) {
this.pointX = pointX;
}
public int getPointY() {
return pointY;
}
public void setPointY(int pointY) {
this.pointY = pointY;
}
}
使用
ValueAnimator valueAnimator=ValueAnimator.ofObject(new PointXYEvaluator(),
new PointXY(pointXY.getLeft(),pointXY.getTop()),new PointXY(pointXY.getLeft()+200,pointXY.getTop()+200));
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
PointXY pointValue= (PointXY) animation.getAnimatedValue();
pointXY.setTranslationX(pointValue.getPointX());
pointXY.setTranslationY(pointValue.getPointY());
}
});
valueAnimator.start();
參考:
自定義控件三部曲之動(dòng)畫篇(六)——ValueAnimator高級(jí)進(jìn)階(二)
Android動(dòng)畫學(xué)習(xí)(三)之使用ValueAnimator和ObjectAnimator實(shí)現(xiàn)動(dòng)畫實(shí)例
2脐瑰、 ObjectAnimator
在ObjectAnimator中,則是先根據(jù)屬性值拼裝成對(duì)應(yīng)的set函數(shù)的名字廷臼,比如這里的scaleY的拼裝方法就是將屬性的第一個(gè)字母強(qiáng)制大寫后苍在,與set拼接,所以就是setScaleY荠商。然后通過反射找到對(duì)應(yīng)控件的setScaleY(float scaleY)函數(shù)寂恬,將當(dāng)前數(shù)字值做為setScaleY(float scale)的參數(shù)將其傳入。
常用的構(gòu)造函數(shù)有:
- ObjectAnimator ofFloat(Object target, String propertyName, float... values)
其中莱没,target指定這個(gè)動(dòng)畫要操作的是哪個(gè)控件
propertyName指定這個(gè)動(dòng)畫要操作這個(gè)控件的哪個(gè)屬性
values是可變長(zhǎng)參數(shù)初肉,就是指這個(gè)屬性值是從哪變到哪 - ObjectAnimator ofFloat(Object target, String xPropertyName, String yPropertyName,Path path)
- ObjectAnimator ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)
代碼如下:
ObjectAnimator translationAnimator=ObjectAnimator.ofFloat(view,"translationY",0,-400).setDuration(400);
translationAnimator.start();
---
Path translationPath=new Path();
translationPath.moveTo(0,0);
translationPath.lineTo(200, 300);
ObjectAnimator translationAnimator=ObjectAnimator.ofFloat(v,"translationX","translationY",translationPath);
translationAnimator.start();
也可以在xml中進(jìn)行配置
<objectAnimator android:duration="400"
android:propertyName="translationY"
android:valueFrom="0dp"
android:valueTo="-200dp"
android:valueType="floatType"/>
---
Animator animator= AnimatorInflater.loadAnimator(Main2Activity.this,R.animator.object_animator);
animator.setTarget(v);
animator.start();
1、View屬性動(dòng)畫默認(rèn)的屬性值:translationX饰躲、translationY牙咏、x 臼隔、 y(view對(duì)象在它容器中的最終位置)、rotation妄壶、rotationX摔握、rotationY、scaleX丁寄、scaleY盒发、pivotX、pivotY(旋轉(zhuǎn)和縮放都是以此為中心展開的,缺省值是 View 對(duì)象的中心點(diǎn))狡逢、alpha...
2宁舰、如果在調(diào)用 ObjectAnimator 的某個(gè)工廠方法時(shí),我們只為 values... 參數(shù)指定了一個(gè)值奢浑,那此值將被認(rèn)定為動(dòng)畫屬性的結(jié)束值蛮艰。 這樣的話,動(dòng)畫顯示的屬性必須帶有一個(gè) getter 方法雀彼,用于獲取動(dòng)畫的起始值壤蚜。
3、還可以自定義屬性值徊哑,但要在操作的控件中袜刷,實(shí)現(xiàn)對(duì)應(yīng)的屬性的set方法
- ObjectAnimator ofObject(T target, @NonNull Property<T, V> property, @Nullable TypeConverter<PointF, V> converter, Path path)
- <T> ObjectAnimator ofFloat(T target, Property<T, Float> xProperty, Property<T, Float> yProperty, Path path)
-
<T, V> ObjectAnimator ofObject(T target, @NonNull Property<T, V> property, @Nullable TypeConverter<PointF, V> converter, Path path)
其中Property<T, V>是一個(gè)屬性包裝器,如下
自定義Property莺丑,代碼如下:
public class ImgMoveView extends View {
private static final String PROPERTY_NAME="position";
public ImgMoveView(Context context) {
super(context);
}
public ImgMoveView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setPosition(PointF position){
int x = Math.round(position.x);
int y = Math.round(position.y);
setTranslationX(x);
setTranslationY(y);
}
public PointF getPosition(){
return new PointF(getX(),getY());
}
/**
* A Property wrapper around the position functionality handled by the
* ImgMoveView#setPosition(PointF) and ImgMoveView#getPosition() methods.
*/
public static final Property<ImgMoveView, PointF> POSITION = new Property<ImgMoveView, PointF>(PointF.class,PROPERTY_NAME) {
@Override
public PointF get(ImgMoveView object) {
return object.getPosition();
}
@Override
public void set(ImgMoveView object, PointF value) {
object.setPosition(value);
}
};
}
調(diào)用:
/*ObjectAnimator pathMoveAnim=ObjectAnimator.ofFloat(imgMove, "translationX", "translationY", path);*/
//ObjectAnimator pathMoveAnim=ObjectAnimator.ofFloat(imgMove, View.TRANSLATION_X, View.TRANSLATION_Y, path);
ObjectAnimator pathMoveAnim=ObjectAnimator.ofObject(imgMove, ImgMoveView.POSITION,
null, path);
參考:自定義控件三部曲之動(dòng)畫篇(七)——ObjectAnimator基本使用著蟹、自定義控件三部曲之動(dòng)畫篇(八)——PropertyValuesHolder與Keyframe
3、監(jiān)聽器
屬性動(dòng)畫提供了AnimatorListener(監(jiān)聽Start梢莽、End萧豆、Cancel、Repeat事件)昏名、AnimatorUpdateListener (onAnimationUpdate())兩個(gè)監(jiān)聽器用于動(dòng)畫在播放過程中的重要?jiǎng)赢嬍录?/p>
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
}
});
4涮雷、AnimatorSet
如果一個(gè)動(dòng)畫用到了一個(gè)對(duì)象的多個(gè)屬性,可以使用AnimatorSet轻局;
可以通過playTogether()洪鸭、playSequentially()、play().with()仑扑、after()览爵、before()來控制執(zhí)行的順序
- AnimatorSet
- playTogether:同時(shí)開始執(zhí)行
- playSequentially:依次按先后順序執(zhí)行,前一個(gè)動(dòng)畫執(zhí)行完夫壁,再執(zhí)行后一個(gè)動(dòng)畫
- AnimatorSet.Builder
- play():調(diào)用AnimatorSet中的play方法拾枣,獲取AnimatorSet.Builder對(duì)象沃疮,
- with():和前面動(dòng)畫同時(shí)開始執(zhí)行
- after(A):A先執(zhí)行盒让,然后執(zhí)行前面的動(dòng)畫
- before(A):前面的動(dòng)畫先執(zhí)行梅肤,A后執(zhí)行
代碼如下:
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.setDuration(1000);
Path translationPath=new Path();
translationPath.moveTo(0,0);
translationPath.lineTo(200, 300);
Path scalePath=new Path();
scalePath.moveTo(1,1);
scalePath.lineTo(0.5f,0.5f);
scalePath.lineTo(1f,1f);
ObjectAnimator translationAnimator=ObjectAnimator.ofFloat(v,"translationX","translationY",translationPath);
ObjectAnimator rotationAnimator=ObjectAnimator.ofFloat(v,"rotation",0,360);
ObjectAnimator scaleAnimator=ObjectAnimator.ofFloat(v,"scaleX","scaleY",scalePath);
//animatorSet.playTogether(translationAnimator,rotationAnimator);//同時(shí)
//animatorSet.playSequentially(translationAnimator,rotationAnimator);//相繼的
animatorSet.play(rotationAnimator).after(translationAnimator).before(scaleAnimator);
animatorSet.start();
---
AnimatorSet animatorSet=new AnimatorSet();
animatorSet.setDuration(1000);
ObjectAnimator translationAnimator=ObjectAnimator.ofFloat(v,"translationY",0,-400).setDuration(400);
ObjectAnimator translationAnimator2=ObjectAnimator.ofFloat(v,"translationY",-400,0).setDuration(400);
ObjectAnimator scaleAnimator=ObjectAnimator.ofFloat(v,"scaleX",1,0.1f,1).setDuration(200);
animatorSet.playSequentially(translationAnimator,scaleAnimator,translationAnimator2);//相繼的
animatorSet.start();
或者使用XML定義
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:ordering="sequentially">
<objectAnimator android:duration="400"
android:propertyName="translationY"
android:valueFrom="0dp"
android:valueTo="-200dp"
android:valueType="floatType"/>
<objectAnimator android:duration="100"
android:propertyName="scaleX"
android:valueFrom="1.0"
android:valueTo="0.1"
android:valueType="floatType"/>
...
</set>
當(dāng)然,對(duì)于同一個(gè)對(duì)象的多個(gè)屬性邑茄,同時(shí)作用動(dòng)畫效果姨蝴,也可以使用PropertyValuesHolder,代碼如下:
PropertyValuesHolder translationHolder=PropertyValuesHolder.ofFloat("translationY",-200);
PropertyValuesHolder rotationHolder=PropertyValuesHolder.ofFloat("rotation",360);
ObjectAnimator objectAnimator=ObjectAnimator.ofPropertyValuesHolder(v, translationHolder, rotationHolder);
objectAnimator.setDuration(1000).start();
objectAnimator.setInterpolator(new BounceInterpolator());
但是肺缕,它不能像AnimatorSet 一樣左医,控制動(dòng)畫執(zhí)行的順序
5、插值器
插值器定義了動(dòng)畫變化過程中的變化規(guī)則同木,需要實(shí)現(xiàn)Interpolator接口
publicinterfaceTimeInterpolator{
floatgetInterpolation(floatinput);
}
其中
- input參數(shù):只與時(shí)間有關(guān)浮梢,取值范圍是0到1,表示當(dāng)前動(dòng)畫的進(jìn)度彤路,取0時(shí)表示動(dòng)畫剛開始秕硝,取1時(shí)表示動(dòng)畫結(jié)束
- 返回值:動(dòng)畫的當(dāng)前 數(shù)值進(jìn)度。取值可以超過1也可以小于0洲尊,超過1表示已經(jīng)超過目標(biāo)值远豺,小于0表示小于開始位置。但這個(gè)數(shù)值是百分比的坞嘀,不是具體數(shù)值躯护,在監(jiān)聽器返回之前,還需要Evaluator進(jìn)行轉(zhuǎn)換
Android系統(tǒng)本身內(nèi)置了一些通用的Interpolator(插值器),如下:
@android:anim/accelerate_interpolator: 越來越快
@android:anim/decelerate_interpolator:越來越慢
@android:anim/accelerate_decelerate_interpolator:先快后慢
@android:anim/anticipate_interpolator: 先后退一小步然后向前加速
@android:anim/overshoot_interpolator:快速到達(dá)終點(diǎn)超出一小步然后回到終點(diǎn)
@android:anim/anticipate_overshoot_interpolator:到達(dá)終點(diǎn)超出一小步然后回到終點(diǎn)
@android:anim/bounce_interpolator:到達(dá)終點(diǎn)產(chǎn)生彈球效果丽涩,彈幾下回到終點(diǎn)
@android:anim/linear_interpolator:均勻速度棺滞。
<!--@anim/cycle_2 -->
<!--定義cycleInterpolator -->
<?xml version="1.0" encoding="utf-8"?>
<cycleInterpolator xmlns:android="http://schemas.android.com/apk/res/android"
android:cycles="2"/>
<!--@anim/shake_error -->
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
android:fromXDelta="0%"
android:toXDelta="2%"
android:duration="300"
android:interpolator="@anim/cycle_2"/>
//加載動(dòng)畫
Login.startAnimation(AnimationUtils.loadAnimation(LoginActivity.this,R.anim.shake_error));
參考:
android動(dòng)畫 Interpolator、自定義控件三部曲之動(dòng)畫篇——插值器
6矢渊、Evaluator
根據(jù)插值器返回的數(shù)字進(jìn)度轉(zhuǎn)成具體數(shù)值检眯;在AnimatorUpdateListener的animation.getAnimatedValue()函數(shù)拿到的就是Evaluator中返回的數(shù)值;系統(tǒng)本身內(nèi)置了一些Evalutor昆淡,如IntEvaluator锰瘸、FloatEvaluator、ArgbEvalutor
自定義Evaluator昂灵,需要實(shí)現(xiàn)TypeEvaluator<T>避凝,要注意動(dòng)畫數(shù)值類型
publicinterfaceTypeEvaluator<T>{
T evaluate(floatfraction,T startValue,T endValue)
}
- fraction:加速器中的返回值,表示當(dāng)前動(dòng)畫的數(shù)值進(jìn)度
- startValue和endValue分別對(duì)應(yīng)ofInt(int start,int end)中的start和end的數(shù)值眨补;
參考:自定義控件三部曲之動(dòng)畫篇——Evaluator管削、Android 動(dòng)畫學(xué)習(xí)(二)之Property Animation初步介紹
7、Keyframe關(guān)鍵幀
KeyframeSet是關(guān)鍵幀的集合撑螺,Keyframe是一個(gè)動(dòng)畫保存time/value(時(shí)間與值)對(duì)
ofInt就是記錄了target,propName,values(是將我們傳入的int型values含思,輾轉(zhuǎn)轉(zhuǎn)化成了PropertyValuesHolder),以及一個(gè)mValueMap,這個(gè)map的key是propName,value是PropertyValuesHolder含潘,在PropertyValuesHolder內(nèi)部又存儲(chǔ)了proprName, valueType , keyframeSet等等
自定義控件三部曲之動(dòng)畫篇(八)——PropertyValuesHolder與Keyframe饲做、Android 屬性動(dòng)畫 源碼解析 深入了解其內(nèi)部實(shí)現(xiàn)、Android Property Animation(屬性動(dòng)畫)原理分析
8遏弱、View的animate()方法
可以使用View的animate()方法直接驅(qū)動(dòng)屬性動(dòng)畫
view.animate().y(100).scaleX(0.1f).setDuration(1000).withStartAction(new Runnable() {
@Override
public void run() {
}
}).withEndAction(new Runnable() {
@Override
public void run() {
}
}).start();
</br>