当我们对一个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));
}
}
外部调用:
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();