# AnimatorDemo **Repository Path**: lzbgit/AnimatorDemo ## Basic Information - **Project Name**: AnimatorDemo - **Description**: 属性动画演示示例 - **Primary Language**: Java - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2018-07-16 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # AnimatorDemo #### 项目介绍 属性动画演示示例 #### 软件架构 软件架构说明 #### 动画执行过程 1. ObjectAnimator ```` public void start() { AnimationHandler.getInstance().autoCancelBasedOn(this); if (DBG) { Log.d(LOG_TAG, "Anim target, duration: " + getTarget() + ", " + getDuration()); for (int i = 0; i < mValues.length; ++i) { PropertyValuesHolder pvh = mValues[i]; Log.d(LOG_TAG, " Values[" + i + "]: " + pvh.getPropertyName() + ", " + pvh.mKeyframes.getValue(0) + ", " + pvh.mKeyframes.getValue(1)); } } //调用父类的start方法,开启动画 super.start(); } ```` 2. ValueAnimator ```` private void start(boolean playBackwards) { //looper 循环者 if (Looper.myLooper() == null) { throw new AndroidRuntimeException("Animators may only be run on Looper threads"); } mReversing = playBackwards; mSelfPulse = !mSuppressSelfPulseRequested; // Special case: reversing from seek-to-0 should act as if not seeked at all. if (playBackwards && mSeekFraction != -1 && mSeekFraction != 0) { if (mRepeatCount == INFINITE) { // Calculate the fraction of the current iteration. float fraction = (float) (mSeekFraction - Math.floor(mSeekFraction)); mSeekFraction = 1 - fraction; } else { mSeekFraction = 1 + mRepeatCount - mSeekFraction; } } mStarted = true; mPaused = false; mRunning = false; mAnimationEndRequested = false; // Resets mLastFrameTime when start() is called, so that if the animation was running, // calling start() would put the animation in the // started-but-not-yet-reached-the-first-frame phase. mLastFrameTime = -1; mFirstFrameTime = -1; mStartTime = -1; //1.调用 addAnimationCallback addAnimationCallback(0); if (mStartDelay == 0 || mSeekFraction >= 0 || mReversing) { // If there's no start delay, init the animation and notify start listeners right away // to be consistent with the previous behavior. Otherwise, postpone this until the first // frame after the start delay. startAnimation(); if (mSeekFraction == -1) { // No seek, start at play time 0. Note that the reason we are not using fraction 0 // is because for animations with 0 duration, we want to be consistent with pre-N // behavior: skip to the final value immediately. setCurrentPlayTime(0); } else { setCurrentFraction(mSeekFraction); } } } ```` ```` private void addAnimationCallback(long delay) { if (!mSelfPulse) { return; } getAnimationHandler().addAnimationFrameCallback(this, delay); } ```` ```` public void addAnimationFrameCallback(final AnimationFrameCallback callback, long delay) { if (mAnimationCallbacks.size() == 0) { //调用AnimationFrameCallbackProvider#postFrameCallback getProvider().postFrameCallback(mFrameCallback); } if (!mAnimationCallbacks.contains(callback)) { mAnimationCallbacks.add(callback); } if (delay > 0) { mDelayedCallbackStartTime.put(callback, (SystemClock.uptimeMillis() + delay)); } } ```` ```` private AnimationFrameCallbackProvider getProvider() { if (mProvider == null) { //AnimationFrameCallbackProvider为接口,实现类 MyFrameCallbackProvider mProvider = new MyFrameCallbackProvider(); } return mProvider; } ```` ```` private class MyFrameCallbackProvider implements AnimationFrameCallbackProvider { final Choreographer mChoreographer = Choreographer.getInstance(); @Override public void postFrameCallback(Choreographer.FrameCallback callback) { //调用 Choreographer 的 postFrameCallback mChoreographer.postFrameCallback(callback); } @Override public void postCommitCallback(Runnable runnable) { mChoreographer.postCallback(Choreographer.CALLBACK_COMMIT, runnable, null); } @Override public long getFrameTime() { return mChoreographer.getFrameTime(); } @Override public long getFrameDelay() { return Choreographer.getFrameDelay(); } @Override public void setFrameDelay(long delay) { Choreographer.setFrameDelay(delay); } } ```` 3. Choreographer ```` public void postFrameCallback(FrameCallback callback) { postFrameCallbackDelayed(callback, 0); } ```` ```` public void postFrameCallbackDelayed(FrameCallback callback, long delayMillis) { if (callback == null) { throw new IllegalArgumentException("callback must not be null"); } postCallbackDelayedInternal(CALLBACK_ANIMATION, callback, FRAME_CALLBACK_TOKEN, delayMillis); } ```` ```` private void postCallbackDelayedInternal(int callbackType, Object action, Object token, long delayMillis) { synchronized (mLock) { final long now = SystemClock.uptimeMillis(); final long dueTime = now + delayMillis; mCallbackQueues[callbackType].addCallbackLocked(dueTime, action, token); if (dueTime <= now) { scheduleFrameLocked(now); } else { //到这里,可以看出通过message进行传递的 Message msg = mHandler.obtainMessage(MSG_DO_SCHEDULE_CALLBACK, action); msg.arg1 = callbackType; msg.setAsynchronous(true); mHandler.sendMessageAtTime(msg, dueTime); } } } ```` ```` 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方法中,执行 doFrame(System.nanoTime(), 0); break; case MSG_DO_SCHEDULE_VSYNC: doScheduleVsync(); break; case MSG_DO_SCHEDULE_CALLBACK: //执行doScheduleCallback最终调用 case MSG_DO_FRAME doScheduleCallback(msg.arg1); break; } } } ```` #### 使用说明 1. xxxx 2. xxxx 3. xxxx #### 参与贡献 1. Fork 本项目 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request #### 码云特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. 码云官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解码云上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是码云最有价值开源项目,是码云综合评定出的优秀开源项目 5. 码云官方提供的使用手册 [http://git.mydoc.io/](http://git.mydoc.io/) 6. 码云封面人物是一档用来展示码云会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)