当我们对一个View进行透明度变化的动画,我们可以这样写:
ValueAnimator fadeAnimator = ObjectAnimator.ofFloat(myView, View.ALPHA, 1.0f, 0.0f);
fadeAnimator.setInterpolator(PathInterpolatorCompat.create(0.33f, 0f, 0.66f, 1f));
fadeAnimator.setDuration(1120);
final AnimatorSet alertAnimator = new AnimatorSet();
alertAnimator.playTogether(fadeAnimator);
alertAnimator.start();
查看View.java的代码,可以看到View.ALPHA的常量
public static final Property<View, Float> ALPHA = new FloatProperty<View>("alpha") {@Overridepublic void setValue(View object, float value) {object.setAlpha(value);}@Overridepublic Float get(View object) {return object.getAlpha();}};
再看setAlpha()方法,如果alpha值变化了invalidate()方法刷新界面
public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha) {ensureTransformationInfo();if (mTransformationInfo.mAlpha != alpha) {mTransformationInfo.mAlpha = alpha;if (onSetAlpha((int) (alpha * 255))) {mPrivateFlags |= PFLAG_ALPHA_SET;// subclass is handling alpha - don't optimize rendering cache invalidationinvalidateParentCaches();invalidate(true);} else {mPrivateFlags &= ~PFLAG_ALPHA_SET;invalidateViewProperty(true, false);mRenderNode.setAlpha(getFinalAlpha());notifyViewAccessibilityStateChangedIfNeeded(AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);}}}
再看getAlpha()方法,返回view当前的alpha值
public float getAlpha() {return mTransformationInfo != null ? mTransformationInfo.mAlpha : 1;}
所以一个自定义的动画,需要一个动画的属性常量,并实现set,get方法,set方法需要判断当动画属性值变化的时候刷新当前View.
例如我们定义圆形波浪动画:
public final static Property<WaveView, Float> RADIUS =new Property<WaveView, Float>(Float.class, "radius") {@Overridepublic Float get(WaveView view) {return view.getRadius();}@Overridepublic void set(WaveView view, Float value) {view.setRadius(value);}};public WaveView setRadius(float radius) {final float oldRadius = mRadius;if (oldRadius != radius) {mRadius = radius;invalidate(mCenterX, mCenterY, oldRadius);if (radius > oldRadius) {invalidate(mCenterX, mCenterY, radius);}}return this;}public final float getRadius() {return mRadius;}
然后在可以Animator调用RADIUS这个属性做动画,例如:
Animator animator = ObjectAnimator.ofFloat(myView, WaveView.RADIUS, 122f, 192f);animator.setInterpolator(PathInterpolatorCompat.create(0.2f, 0f, 0.24f, 1f));animator.setDuration(1120);final ValueAnimator fadeAnimator = ObjectAnimator.ofFloat(myView, View.ALPHA, 1.0f, 0.0f);fadeAnimator.setInterpolator(PathInterpolatorCompat.create(0.33f, 0f, 0.66f, 1f));fadeAnimator.setDuration(1120);final AnimatorSet alertAnimator = new AnimatorSet();alertAnimator.playTogether(animator, fadeAnimator);alertAnimator.start();
完整的Demo例子:
package com.usetsai.myalarm;import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Property;
import android.view.View;/*** Created by junliang on 16-7-6.*/
public class WaveView extends View {public final static Property<WaveView, Integer> FILL_COLOR =new Property<WaveView, Integer>(Integer.class, "fillColor") {@Overridepublic Integer get(WaveView view) {return view.getFillColor();}@Overridepublic void set(WaveView view, Integer value) {view.setFillColor(value);}};public final static Property<WaveView, Float> RADIUS =new Property<WaveView, Float>(Float.class, "radius") {@Overridepublic Float get(WaveView view) {return view.getRadius();}@Overridepublic void set(WaveView view, Float value) {view.setRadius(value);}};private final Paint mCirclePaint = new Paint();private float mCenterX;private float mCenterY;private float mRadius;private float mStrokeWidth;public WaveView(Context context) {this(context, null /* attrs */);}public WaveView(Context context, AttributeSet attrs) {this(context, attrs, 0 /* defStyleAttr */);}public WaveView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.WaveView, defStyleAttr, 0 /* defStyleRes */);mCenterX = a.getDimension(R.styleable.WaveView_centerX, 0.0f);mCenterY = a.getDimension(R.styleable.WaveView_centerY, 0.0f);mRadius = a.getDimension(R.styleable.WaveView_radius, 0.0f);mStrokeWidth = a.getDimension(R.styleable.WaveView_strokeWidth, 3f);int fillColor = a.getColor(R.styleable.WaveView_fillColor, Color.BLUE);int fillEndColor = a.getColor(R.styleable.WaveView_fillEndColor, -1);if (fillEndColor == -1) {mCirclePaint.setColor(fillColor);} else {LinearGradient sweepGradient = new LinearGradient(0f,a.getDimension(R.styleable.WaveView_gradientStart, 0f),0f, a.getDimension(R.styleable.WaveView_gradientEnd, 0f),fillColor, fillEndColor, Shader.TileMode.CLAMP);mCirclePaint.setShader(sweepGradient);}mCirclePaint.setAntiAlias(true);mCirclePaint.setStyle(Paint.Style.STROKE);mCirclePaint.setStrokeWidth(mStrokeWidth);a.recycle();}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawCircle(mCenterX, mCenterY, mRadius, mCirclePaint);}public final int getFillColor() {return mCirclePaint.getColor();}public WaveView setFillColor(int color) {if (mCirclePaint.getColor() != color) {mCirclePaint.setColor(color);invalidate(mCenterX, mCenterY, mRadius);}return this;}public final float getCenterX() {return mCenterX;}public WaveView setCenterX(float centerX) {final float oldCenterX = mCenterX;if (oldCenterX != centerX) {mCenterX = centerX;invalidate(oldCenterX, mCenterY, mRadius);invalidate(centerX, mCenterY, mRadius);}return this;}public final float getCenterY() {return mCenterY;}public WaveView setCenterY(float centerY) {final float oldCenterY = mCenterY;if (oldCenterY != centerY) {mCenterY = centerY;invalidate(mCenterX, oldCenterY, mRadius);invalidate(mCenterX, centerY, mRadius);}return this;}public final float getRadius() {return mRadius;}public WaveView setRadius(float radius) {final float oldRadius = mRadius;if (oldRadius != radius) {mRadius = radius;invalidate(mCenterX, mCenterY, oldRadius);if (radius > oldRadius) {invalidate(mCenterX, mCenterY, radius);}}return this;}private void invalidate(float centerX, float centerY, float radius) {invalidate((int) (centerX - radius - 0.5f), (int) (centerY - radius - 0.5f),(int) (centerX + radius + 0.5f), (int) (centerY + radius + 0.5f));}
}
外部调用:
Animator animator = ObjectAnimator.ofFloat(myView, WaveView.RADIUS, 122f, 192f);animator.setInterpolator(PathInterpolatorCompat.create(0.2f, 0f, 0.24f, 1f));animator.setDuration(1120);final ValueAnimator fadeAnimator = ObjectAnimator.ofFloat(myView, View.ALPHA, 1.0f, 0.0f);fadeAnimator.setInterpolator(PathInterpolatorCompat.create(0.33f, 0f, 0.66f, 1f));fadeAnimator.setDuration(1120);final AnimatorSet alertAnimator = new AnimatorSet();alertAnimator.playTogether(animator, fadeAnimator);alertAnimator.start();