动画类型
帧动画:就是xml文件里面定义的一帧一帧的动画
view动画(animation类):就是translate,scale,alpha,rotate
属性动画(ObjectAnimator类):可以设置translateX,时间之类的属性动画,在rb32寸屏有用过
view动画典型调用
ImageView iv = (ImageView) findViewById(R.id.iv);
Animation animation = new TranslateAnimation(logoFocus.getLeft(), logoFocus.getLeft()+150, logoFocus.getTop(), iv.getTop());
animation.setDuration(1000);
animation.setFillAfter(true);
animation.setFillEnabled(true);
iv.startAnimation(animSurprise2Movement);
view动画流程分析
1、在View类,设置动画,开始动画
public void startAnimation(Animation animation) {
animation.setStartTime(Animation.START_ON_FIRST_FRAME);
setAnimation(animation);
invalidateParentCaches();
invalidate(true);
}
2、先追溯到ViewRootImpl类,然后到ViewGroup类
public final class ViewRootImpl implements ViewParent,
View.AttachInfo.Callbacks, ThreadedRenderer.DrawCallbacks {
1、scheduleTraversals();
2、doTraversal();
3、performTraversals();
4、performDraw()
5、draw(fullRedrawNeeded);
6、drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty)
7、mView.draw(canvas);
}
public class ViewGroup implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
1、mView.draw(canvas);
2、dispatchDraw(canvas)
3、drawChild(canvas, transientChild, drawingTime)
}
中间还有一些其他调用,这里省去,后续来到了ViewGroup类
public abstract class ViewGroup extends View implements ViewParent, ViewManager {
@Override
protected void dispatchDraw(Canvas canvas) {
...
drawChild(canvas, transientChild, drawingTime);
...
}
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
return child.draw(canvas, this, drawingTime);
}
}
3、在view类draw()方法调用了applyLegacyAnimation()方法
- 计算animation的位移
- animation开始回调
- parent.invalidate刷新界面
public class View implements Drawable.Callback, KeyEvent.Callback,
AccessibilityEventSource {
boolean draw(Canvas canvas, ViewGroup parent, long drawingTime) {
...
more = applyLegacyAnimation(parent, drawingTime, a, scalingRequired);
...
}
private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
Animation a, boolean scalingRequired) {
...
onAnimationStart();
...
a.getTransformation(drawingTime, invalidationTransform, 1f);
...
parent.invalidate(mLeft, mTop, mRight, mBottom);
}
}
5、animation类的getTransformation()方法
public abstract class Animation implements Cloneable {
public boolean getTransformation(long currentTime, Transformation outTransformation) {
...
动画开始回调
fireAnimationStart();
...
动画重复回调
fireAnimationRepeat();
...
动画结束回调
fireAnimationEnd();
}
private void fireAnimationStart() {
if (mListener != null) {
if (mListenerHandler == null) mListener.onAnimationStart(this);
else mListenerHandler.postAtFrontOfQueue(mOnStart);
}
}
private void fireAnimationRepeat() {
if (mListener != null) {
if (mListenerHandler == null) mListener.onAnimationRepeat(this);
else mListenerHandler.postAtFrontOfQueue(mOnRepeat);
}
}
private void fireAnimationEnd() {
if (mListener != null) {
if (mListenerHandler == null) mListener.onAnimationEnd(this);
else mListenerHandler.postAtFrontOfQueue(mOnEnd);
}
}
}
属性动画原理
1、典型调用
ObjectAnimator animator = ObjectAnimator.ofFloat(circleProgress, "progress", 0f, 1f)
animator.duration = 3000
animator.interpolator = LinearInterpolator()
animator.start()
2、流程分析
public final class ObjectAnimator extends ValueAnimator {
public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) {
ObjectAnimator anim = new ObjectAnimator(target, propertyName);
anim.setFloatValues(values);
return anim;
}
private ObjectAnimator(Object target, String propertyName) {
setTarget(target);
setPropertyName(propertyName);
}
public void setTarget(@Nullable Object target) {
final Object oldTarget = getTarget();
if (oldTarget != target) {
if (isStarted()) {
cancel();
}
mTarget = target == null ? null : new WeakReference<Object>(target);
// New target should cause re-initialization prior to starting
mInitialized = false;
}
}
public void setPropertyName(@NonNull String propertyName) {
// mValues could be null if this is being constructed piecemeal. Just record the
// propertyName to be used later when setValues() is called if so.
if (mValues != null) {
PropertyValuesHolder valuesHolder = mValues[0];
String oldName = valuesHolder.getPropertyName();
valuesHolder.setPropertyName(propertyName);
mValuesMap.remove(oldName);
mValuesMap.put(propertyName, valuesHolder);
}
mPropertyName = propertyName;
// New property/values/target should cause re-initialization prior to starting
mInitialized = false;
}
}
3、开始动画,初始化每个属性
public class ValueAnimator extends Animator implements AnimationHandler.AnimationFrameCallback {
@Override
public void start() {
start(false);
}
private void start(boolean playBackwards) {
...
addAnimationCallback(0);
startAnimation();
...
}
private void startAnimation() {
...
initAnimation();
...
notifyStartListeners();
...
}
private void notifyStartListeners() {
...
tmpListeners.get(i).onAnimationStart(this, mReversing);
...
}
PropertyValuesHolder[] mValues;
void initAnimation() {
if (!mInitialized) {
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].init();
}
mInitialized = true;
}
}
}
4、会调用PropertyValuesHolder的init()方法
- 没有估值器则new一个
- 准备mKeyframes(里面包含了属性值),设置估值器,
public class PropertyValuesHolder implements Cloneable {
void init() {
if (mEvaluator == null) {
// We already handle int and float automatically, but not their Object
// equivalents
mEvaluator = (mValueType == Integer.class) ? sIntEvaluator :
(mValueType == Float.class) ? sFloatEvaluator :
null;
}
if (mEvaluator != null) {
// KeyframeSet knows how to evaluate the common types - only give it a custom
// evaluator if one has been set on this class
mKeyframes.setEvaluator(mEvaluator);
}
}
动画初始化时候调用的
public static PropertyValuesHolder ofFloat(String propertyName, float... values) {
return new FloatPropertyValuesHolder(propertyName, values);
}
public FloatPropertyValuesHolder(String propertyName, float... values) {
super(propertyName);
setFloatValues(values);
}
ObjectAnimator类ofFloat方法调用
public void setFloatValues(float... values) {
mValueType = float.class;
mKeyframes = KeyframeSet.ofFloat(values);
}
}
5、在开始动画,刷新动画,在addAnimationCallback(0)这个方法,然后在回调的doAnimationFrame(long frameTime)方法中,有开始动画,刷新动画,结束动画三个状态
public class ValueAnimator extends Animator implements
AnimationHandler.AnimationFrameCallback {
@Override
public void start() {
start(false);
}
private void start(boolean playBackwards) {
...
addAnimationCallback(0);
startAnimation();
...
}
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}
public AnimationHandler getAnimationHandler() {
return AnimationHandler.getInstance();
}
public final boolean doAnimationFrame(long frameTime) {
// 回调开始动画
startAnimation();
// 回调更新动画
boolean finished = animateBasedOnTime(currentTime);
if (finished) {
// 回调结束动画
endAnimation();
}
return finished;
}
boolean animateBasedOnTime(long currentTime) {
...
animateValue(currentIterationFraction);
...
return done;
}
}
6、我们继续跟踪是怎么调用的
public class AnimationHandler {
public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) {
if (mAnimationCallbacks.size() == 0) {
实际调用的是 mChoreographer.postFrameCallback(callback);
getProvider().postFrameCallback(mFrameCallback);
}
if (!mAnimationCallbacks.contains(callback)) {
mAnimationCallbacks.add(callback);
}
}
private AnimationFrameCallbackProvider getProvider() {
if (mProvider == null) {
mProvider = new MyFrameCallbackProvider();
}
return mProvider;
}
private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider {
final Choreographer mChoreographer = Choreographer.getInstance();
@Override
public void postFrameCallback(Choreographer.FrameCallback callback) {
mChoreographer.postFrameCallback(callback);
// 实际调用 postFrameCallbackDelayed(callback, 0);
}
...
}
private final Choreographer.FrameCallback mFrameCallback = new Choreographer.FrameCallback() {
@Override
public void doFrame(long frameTimeNanos) {
doAnimationFrame(getProvider().getFrameTime());
if (mAnimationCallbacks.size() > 0) {
getProvider().postFrameCallback(this);
}
}
};
}
public final class Choreographer {
public void postFrameCallback(FrameCallback callback) {
postFrameCallbackDelayed(callback, 0);
}
public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) {
postCallbackDelayedInternal(CALLBACK_ANIMATION,
callback, FRAME_CALLBACK_TOKEN, delayMillis);
}
private void postCallbackDelayedInternal(int callbackType,
Object action, Object token, long delayMillis) {
...
if (dueTime <= now) {
scheduleFrameLocked(now);
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action);
msg.arg1 = callbackType;
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, dueTime);
}
}
}
private void scheduleFrameLocked(long now) {
if (!mFrameScheduled) {
mFrameScheduled = true;
if (USE_VSYNC) {
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame on vsync.");
}
// If running on the Looper thread, then schedule the vsync immediately,
// otherwise post a message to schedule the vsync from the UI thread
// as soon as possible.
if (isRunningOnLooperThreadLocked()) {
scheduleVsyncLocked();
} else {
Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_VSYNC);
msg.setAsynchronous(true);
mHandler.sendMessageAtFrontOfQueue(msg);
}
} else {
final long nextFrameTime = Math.max(
mLastFrameTimeNanos / TimeUtils.NANOS_PER_MS + sFrameDelay, now);
if (DEBUG_FRAMES) {
Log.d(TAG, "Scheduling next frame in " + (nextFrameTime - now) + " ms.");
}
Message msg = mHandler.obtainMessage(MSG_DO_FRAME);
msg.setAsynchronous(true);
mHandler.sendMessageAtTime(msg, nextFrameTime);
}
}
}
private final class FrameHandler extends Handler {
public FrameHandler(Looper looper) {
super(looper);
}
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case MSG_DO_FRAME:
doFrame(System.nanoTime(), 0);
break;
case MSG_DO_SCHEDULE_VSYNC:
doScheduleVsync();
break;
case MSG_DO_SCHEDULE_CALLBACK:
doScheduleCallback(msg.arg1);
break;
}
}
}
void doFrame(long frameTimeNanos, int frame) {
...
AnimationUtils.lockAnimationClock(frameTimeNanos / TimeUtils.NANOS_PER_MS);
mFrameInfo.markInputHandlingStart();
doCallbacks(Choreographer.CALLBACK_INPUT, frameTimeNanos);
mFrameInfo.markAnimationsStart();
doCallbacks(Choreographer.CALLBACK_ANIMATION, frameTimeNanos);
mFrameInfo.markPerformTraversalsStart();
doCallbacks(Choreographer.CALLBACK_TRAVERSAL, frameTimeNanos);
doCallbacks(Choreographer.CALLBACK_COMMIT, frameTimeNanos);
...
}
void doCallbacks(int callbackType, long frameTimeNanos) {
...
for (CallbackRecord c = callbacks; c != null; c = c.next) {
c.run(frameTimeNanos);
}
...
}
}
7、终于来到了doFrame(frameTimeNanos);方法
private static final class CallbackRecord {
public void run(long frameTimeNanos) {
if (token == FRAME_CALLBACK_TOKEN) {
((FrameCallback)action).doFrame(frameTimeNanos);
} else {
((Runnable)action).run();
}
}
}
8、最后我们看一下怎么调用动画属性
public class ValueAnimator extends Animator implements
AnimationHandler.AnimationFrameCallback {
@Override
public void start() {
start(false);
}
private void start(boolean playBackwards) {
...
addAnimationCallback(0);
startAnimation();
...
}
private void addAnimationCallback(long delay) {
if (!mSelfPulse) {
return;
}
getAnimationHandler().addAnimationFrameCallback(this, delay);
}
public AnimationHandler getAnimationHandler() {
return AnimationHandler.getInstance();
}
public final boolean doAnimationFrame(long frameTime) {
// 回调开始动画
startAnimation();
// 回调更新动画
boolean finished = animateBasedOnTime(currentTime);
if (finished) {
// 回调结束动画
endAnimation();
}
return finished;
}
boolean animateBasedOnTime(long currentTime) {
...
animateValue(currentIterationFraction);
...
return done;
}
}
9、在animateValue(currentIterationFraction);方法中,调用了setAnimatedValue给每个属性赋值
public final class ObjectAnimator extends ValueAnimator {
void animateValue(float fraction) {
final Object target = getTarget();
...
super.animateValue(fraction);
int numValues = mValues.length;
for (int i = 0; i < numValues; ++i) {
mValues[i].setAnimatedValue(target);
}
}
}
10、最后调用反射赋值
public class PropertyValuesHolder implements Cloneable {
void setAnimatedValue(Object target) {
if (mIntProperty != null) {
mIntProperty.setValue(target, mIntAnimatedValue);
return;
}
if (mProperty != null) {
mProperty.set(target, mIntAnimatedValue);
return;
}
if (mJniSetter != 0) {
nCallIntMethod(target, mJniSetter, mIntAnimatedValue);
return;
}
if (mSetter != null) {
try {
mTmpValueArray[0] = mIntAnimatedValue;
mSetter.invoke(target, mTmpValueArray);
} catch (InvocationTargetException e) {
Log.e("PropertyValuesHolder", e.toString());
} catch (IllegalAccessException e) {
Log.e("PropertyValuesHolder", e.toString());
}
}
}
native static private void nCallIntMethod(Object target, long methodID, int arg);
}
插值器和估值器
插值器(TimeInterpolator)
- 定义动画变化效果
- 系统有9个自带插值器
1、动画加速进行,@android:anim/accelerate_interpolator,AccelerateInterpolator
2、快速完成动画,超出再回到结束样式,@android:anim/overshoot_interpolator,OvershootInterpolator
3、先加速再减速,@android:anim/accelerate_decelerate_interpolator,AccelerateDecelerateInterpolator
4、先退后再加速前进,@android:anim/anticipate_interpolator,AnticipateInterpolator
5、先退后再加速前进,超出终点后再回终点,@android:anim/anticipate_overshoot_interpolator,AnticipateOvershootInterpolator
6、最后阶段弹球效果,@android:anim/bounce_interpolator,BounceInterpolator
7、周期运动,@android:anim/cycle_interpolator,CycleInterpolator
8、减速,@android:anim/decelerate_interpolator,DecelerateInterpolator
9、匀速,@android:anim/linear_interpolator,LinearInterpolator
public abstract class Animation implements Cloneable {
public void setInterpolator(Interpolator i) {
mInterpolator = i;
}
public boolean getTransformation(long currentTime, Transformation outTransformation) {
...
final float interpolatedTime = mInterpolator.getInterpolation(normalizedTime);
applyTransformation(interpolatedTime, outTransformation);
...
}
}
/**
* An interpolator defines the rate of change of an animation. This allows
* the basic animation effects (alpha, scale, translate, rotate) to be
* accelerated, decelerated, repeated, etc.
*/
大概意思就是,定义了动画变化的频率(加速,减速,重复)
public interface Interpolator extends TimeInterpolator {
}
public interface TimeInterpolator {
float getInterpolation(float input);
}
在具体的动画中,根据插值器返回的时间算变化的距离
public class TranslateAnimation extends Animation {
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
float dx = mFromXDelta;
float dy = mFromYDelta;
if (mFromXDelta != mToXDelta) {
dx = mFromXDelta + ((mToXDelta - mFromXDelta) * interpolatedTime);
}
if (mFromYDelta != mToYDelta) {
dy = mFromYDelta + ((mToYDelta - mFromYDelta) * interpolatedTime);
}
t.getMatrix().setTranslate(dx, dy);
}
}
估值器(TypeEvaluator)
- 定义了动画变化效果具体的值
- 属性动画特有的属性
private ObjectAnimator createNullAnimator(ImageView imageView) {
return ObjectAnimator.ofObject(imageView, ANIMATED_TRANSFORM_PROPERTY,
NULL_MATRIX_EVALUATOR, null, null);
}
private static TypeEvaluator<Matrix> NULL_MATRIX_EVALUATOR = new TypeEvaluator<Matrix>() {
@Override
public Matrix evaluate(float fraction, Matrix startValue, Matrix endValue) {
return null;
}
};