Android自定义属性动画

当我们对一个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 ALPHA = new FloatProperty("alpha") { @Override public void setValue(View object, float value) { object.setAlpha(value); }@Override public 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 invalidation invalidateParentCaches(); 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 RADIUS = new Property(Float.class, "radius") { @Override public Float get(WaveView view) { return view.getRadius(); }@Override public 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 FILL_COLOR = new Property(Integer.class, "fillColor") { @Override public Integer get(WaveView view) { return view.getFillColor(); }@Override public void set(WaveView view, Integer value) { view.setFillColor(value); } }; public final static Property RADIUS = new Property(Float.class, "radius") { @Override public Float get(WaveView view) { return view.getRadius(); }@Override public 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(); }@Override protected 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)); } }


【Android自定义属性动画】外部调用:
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();




    推荐阅读