Android屬性動畫
屬性動畫
屬性動畫的核心主要是ObjectAnimator,ValueAnimator這幾個對象的使用。下面對各個方法的使用進行介紹。
ObjectAnimator的使用:
一.單個動畫的使用:
y軸旋轉從0度旋轉到360度
ObjectAnimator .ofFloat(imageView,"rotationY",0,360) .setDuration(1000) .start();
x軸旋轉從0度旋轉到360度
ObjectAnimator .ofFloat(imageView,"rotationX",0,360) .setDuration(1000) .start();
寬度從原始長度到1.5倍長度
ObjectAnimator .ofFloat(imageView,"scaleX",1f,1.5f) .setDuration(1000) .start();
高度從原始長度到1.5倍長度
ObjectAnimator .ofFloat(imageView,"scaleY",1f,1.5f) .setDuration(1000) .start();
沿著x軸正方向從原始位置移動到相對於原始位置100px的位置
ObjectAnimator .ofFloat(imageView,"translationX",0,100) .setDuration(1000) .start();
沿著y軸正方向從原始位置移動到相對於原始位置100px的位置
ObjectAnimator .ofFloat(imageView,"translationY",0,100) .setDuration(1000) .start();
透明度從不透明到完全透明
ObjectAnimator .ofFloat(imageView,"alpha",1,0) .setDuration(1000) .start();
顏色改變動畫,需要用到ObjectAnimator.ofArgb()方法(需要在API Level 21及以上的版本使用),如下是改變textView的背景顏色。
int startColor = 0xffff0000;int endColor = 0xff00ff00;ObjectAnimator.ofArgb(textView,"backgroundColor",startColor,endColor).setDuration(1000).start();
二.混合動畫的使用:針對一個View的混合動畫主要使用到了PropertyValuesHolder,如果你想把scaleX和scaleY結合起來使用,那麼需要構造兩個對應的PropertyValuesHolder對象,最後再調用ObjectAnimator.ofPropertyValuesHolder,如下:
PropertyValuesHolder propertyValuesHolder1 = PropertyValuesHolder.ofFloat( "scaleX", 1f, 1.5f);PropertyValuesHolder propertyValuesHolder2 = PropertyValuesHolder.ofFloat("scaleY", 1f, 1.5f);ObjectAnimator.ofPropertyValuesHolder(imageView,propertyValuesHolder1,propertyValuesHolder2).setDuration(3000).start();
AnimatorSet的使用
ObjectAnimator animator1 = ObjectAnimator.ofFloat(imageView,"scaleX",1f,4f,1f);ObjectAnimator animator2 = ObjectAnimator.ofFloat(imageView,"scaleY",1f,4f,1f);AnimatorSet animSet = new AnimatorSet();//animSet.play(animator1).with(animator2);//一起執行animSet.play(animator1).after(animator2);//animator1在animator2執行完後執行//animSet.play(animator1).before(animator2);//animator1在animator2前執行//animSet.playTogether(animator1,animator2);////一起執行animSet.setDuration(2000);animSet.start();
兩個屬性的值隨著Path進行變換(需要在API Level 21及以上的版本使用)
Path path = new Path();//這邊是一個矩形路徑,前4個值是left,top,right,bottom值,最後一個參數表示動畫的方向(CW代表順時針和CCW代表逆時針)。path.addRect(10,10,300,300,Path.Direction.CW); ObjectAnimator.ofFloat(imageView,"translationX","translationY",path).setDuration(3000).start();
三.自訂屬性動畫:使用下面的API實現自訂的屬性動畫
ofFloat(T target, Property property, float... values)
執行個體:
自訂的CircleView:
public class CircleView extends View { private Paint paint; private float radius; public float getRadius() { return radius; } public void setRadius(float radius) { this.radius = radius; public CircleView(Context context) { super(context); } public CircleView(Context context, AttributeSet attrs) { super(context, attrs); } public CircleView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onDraw(Canvas canvas) { if (paint == null) { paint = new Paint(); paint.setColor(getResources().getColor( android.R.color.holo_red_light)); } canvas.drawCircle(getWidth()/2, getHeight()/2, radius, paint); }}
動畫執行代碼:
Property property = new Property(Float.class, "radius") { @Override public Float get(CircleView object) { return object.getRadius(); } @Override public void set(CircleView object, Float value) { object.setRadius(value); }};ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(circleView, property, 10f,100f,10f);objectAnimator.setRepeatCount(10);objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { circleView.invalidate(); }});objectAnimator.setDuration(2000);objectAnimator.start();
xml布局:
執行個體效果:
ValueAnimator的使用
ValueAnimator類是我們上面說到的ObjectAnimator的父類,閱讀源碼,我們可以發現ObjectAnimator動畫最終是通過ValueAnimation實現的。下面就來說說ValueAnimator的使用。
單個值變化 ,imageView沿著x軸從1移動到100,這邊其實把ValueAnimator換成ObjectAnimator也是一樣的效果,因為ObjectAnimator是ValueAnimator的子類。
ValueAnimator valueAnimator = ValueAnimator.ofFloat(1,100);valueAnimator.setDuration(1000);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { imageView.setTranslationX((Float) animation.getAnimatedValue()); } });valueAnimator.start();
多個值變化
PropertyValuesHolder property1 = PropertyValuesHolder.ofFloat("value1", 1,100);PropertyValuesHolder property2 = PropertyValuesHolder.ofFloat("value2", 100, 200);ValueAnimator valueAnimator = ValueAnimator .ofPropertyValuesHolder(property1, property2);valueAnimator.setDuration(1000);valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value1 = (float) animation.getAnimatedValue("value1"); float value2 = (float) animation.getAnimatedValue("value2"); imageView.setTranslationX(value1); imageView.setTranslationY(value2); }});valueAnimator.start();
使用setEvaluator(TypeEvaluator value)來計算AnimatedValue,實現進階的動畫效果。
樣本: 電商類APP常用的一個動畫情境,把商品加入購物車,商品呈曲線掉入購入車。
源碼地址:https://github.com/heheLT/AnimationBall
:
主要代碼:
/*** 二階賽貝爾曲線,由三個點確定一條曲線*/public void paoWuXian(final int[] startLocation, final int[] endLocation, final ViewanimalView, final View endView) { final float[] middle = new float[2]; middle[0] = endLocation[0];//中間點的x,這邊也可以取其他值 middle[1] = startLocation[1];//中間點的y,這邊也可以取其他值 ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setDuration(1000); valueAnimator.setObjectValues(new PointF(endLocation[0], endLocation[1])); valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); valueAnimator.setEvaluator(new TypeEvaluator() { @Override public PointF evaluate(float fraction, PointF startValue, PointF endValue) { PointF point = new PointF(); //這邊利用的是二階貝茲路徑公式計算x,y point.x = (1 - fraction) * (1 - fraction) * startLocation[0] + 2 * fraction * (1 - fraction) * middle[0] + fraction * fraction * endLocation[0]; point.y = (1 - fraction) * (1 - fraction) * startLocation[1] + 2 * fraction * (1 - fraction) * middle[1] + fraction * fraction * endLocation[1]; return point; } }); valueAnimator.start(); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { PointF point = (PointF) animation.getAnimatedValue(); animalView.setX(point.x); animalView.setY(point.y); } }); valueAnimator.addListener(new ValueAnimator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { //拋物線動畫結束後,進行縮放動畫 ValueAnimator valueAnimator = new ValueAnimator(); valueAnimator.setDuration(400); valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator()); valueAnimator.setObjectValues(1.0f, 0.8f); valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { float value = (float) animation.getAnimatedValue(); if (value > 0.9) { endView.setScaleX(value); endView.setScaleY(value); } else { endView.setScaleX(1.8f - value); endView.setScaleY(1.8f - value); } } }); valueAnimator.start(); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } });}
ValueAnimator總結:
ValueAnimator其實是一個控制值變化的輔助類,我們設定了變化得起點,終點以及時間,這樣ValueAnimator提供了一個值變化的監聽介面,這樣就可以拿到變化的值,然後設定到View上面,形成動畫。我們可以通過setEvaluator(TypeEvaluator value)來計算AnimatedValue的值,實現自訂動畫。