<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # Property Animation ## 屬性動畫的優點 - 屬性動畫顧名思義就是改變了View的屬性,而不僅僅是繪制的位置。 - 屬性動畫可以操作的屬性相比于補間動畫大大增加,除了常用的平移、旋轉、縮放、透明度還有顏色等,基本上能通過View.setXX來設置的屬性,屬性動畫都可以操作,這大大增加了我們在使用動畫時的靈活性。 - 屬性動畫分為ObjectAnimator和ValueAnimator,其中ObjectAnimator是繼承于ValueAnimator。 ## ValueAnimator > ValueAnimator并不會改變屬性的大小,他只是在一段時間生成某些值。我們需要做的是監聽這些值得改變從而該改變View的屬性,進而產生動畫效果。 下邊的動畫就是對mView進行平移: ``` ValueAnimator animator = ValueAnimator.ofFloat(0, 1000); anim.addUpdateListener(new AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mView.setTranslationX(animation.getAnimatedValue()); } }); animator.setDuration(1000).start() ``` ## ObjectAnimator > 在ValueAnimator的基礎之上,對控件的某個屬性執行一次動畫。 相同的對mView進行平移的動畫ObjectAnimator是這樣實現的: ``` ObjectAnimator animator=ObjectAnimator.ofFloat (mView,"translationX",0,1000); animator.setDuration (1000); animator.start (); ``` ## PropertyAnimation流程圖 ![](../images/PropertyAnimation流程圖.png) ## 屬性動畫代碼的執行過程 ### start #### ObjectAnimator.start ``` public final class ObjectAnimator extends ValueAnimator { /***部分代碼省略***/ @Override public void start() { //首先依次判斷了當前動畫、等待的動畫、延遲的動畫中是否有和當前動畫相同的動畫 //若有就把相同的動畫取消掉 // See if any of the current active/pending animators need to be canceled AnimationHandler handler = sAnimationHandler.get(); if (handler != null) { int numAnims = handler.mAnimations.size(); for (int i = numAnims - 1; i >= 0; i--) { if (handler.mAnimations.get(i) instanceof ObjectAnimator) { ObjectAnimator anim = (ObjectAnimator) handler.mAnimations.get(i); if (anim.mAutoCancel && hasSameTargetAndProperties(anim)) { anim.cancel(); } } } /***部分代碼省略***/ } /***部分代碼省略***/ //然后調用ValueAnimator.start()方法 super.start(); } } ``` #### ValueAnimator.start ``` public class ValueAnimator extends Animator { /***部分代碼省略***/ protected static ThreadLocal<AnimationHandler> sAnimationHandler = new ThreadLocal<AnimationHandler>(); //保證每個線程有且只有一個AnimationHandler private static AnimationHandler getOrCreateAnimationHandler() { AnimationHandler handler = sAnimationHandler.get(); if (handler == null) { handler = new AnimationHandler(); sAnimationHandler.set(handler); } return handler; } @Override public void start() { start(false); } private void start(boolean playBackwards) { if (Looper.myLooper() == null) { throw new AndroidRuntimeException("Animators may only be run on Looper threads"); } /***部分代碼省略***/ //創建或者獲取animationHandler實例 AnimationHandler animationHandler = getOrCreateAnimationHandler(); animationHandler.mPendingAnimations.add(this); if (mStartDelay == 0) { // This sets the initial value of the animation, prior to actually starting it running if (prevPlayingState != SEEKED) { setCurrentPlayTime(0); } mPlayingState = STOPPED; mRunning = true; //回調監聽器,通知動畫開始 notifyStartListeners(); } //開始動畫 animationHandler.start(); } //回調監聽器,通知動畫開始 private void notifyStartListeners() { if (mListeners != null && !mStartListenersCalled) { ArrayList<AnimatorListener> tmpListeners = (ArrayList<AnimatorListener>) mListeners.clone(); int numListeners = tmpListeners.size(); for (int i = 0; i < numListeners; ++i) { tmpListeners.get(i).onAnimationStart(this); } } mStartListenersCalled = true; } public void setCurrentPlayTime(long playTime) { float fraction = mUnscaledDuration > 0 ? (float) playTime / mUnscaledDuration : 1; setCurrentFraction(fraction); } public void setCurrentFraction(float fraction) { //初始化動畫 initAnimation(); if (fraction < 0) { fraction = 0; } /***部分代碼省略***/ } } ``` #### AnimationHandler.start ``` public class ValueAnimator extends Animator { /***部分代碼省略***/ protected static class AnimationHandler implements Runnable { /***部分代碼省略***/ //開始動畫 public void start() { scheduleAnimation(); } //發送VSYNC信號回調請求 private void scheduleAnimation() { if (!mAnimationScheduled) { mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, this, null); mAnimationScheduled = true; } } // Called by the Choreographer. //Choreographer的VSYNC信號回調 @Override public void run() { mAnimationScheduled = false; doAnimationFrame(mChoreographer.getFrameTime()); } private void doAnimationFrame(long frameTime) { /***部分代碼省略***/ // Now process all active animations. The return value from animationFrame() // tells the handler whether it should now be ended int numAnims = mAnimations.size(); for (int i = 0; i < numAnims; ++i) { mTmpAnimations.add(mAnimations.get(i)); } for (int i = 0; i < numAnims; ++i) { ValueAnimator anim = mTmpAnimations.get(i); //執行動畫 //doAnimationFrame方法返回ture,則該動畫添加在mEndingAnims隊列中進行end操作 if (mAnimations.contains(anim) && anim.doAnimationFrame(frameTime)) { mEndingAnims.add(anim); } } /***部分代碼省略***/ //循環執行,直到endAnimation將mAnimations置空 if (!mAnimations.isEmpty() || !mDelayedAnims.isEmpty()) { scheduleAnimation(); } } } } ``` ### init #### ObjectAnimator.initAnimation ``` public final class ObjectAnimator extends ValueAnimator { /***部分代碼省略***/ @Override void initAnimation() { if (!mInitialized) { // mValueType may change due to setter/getter setup; do this before calling super.init(), // which uses mValueType to set up the default type evaluator. final Object target = getTarget(); if (target != null) { final int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { mValues[i].setupSetterAndGetter(target); } } super.initAnimation(); } } } ``` #### setupSetterAndGetter ``` public final class ObjectAnimator extends ValueAnimator { /***部分代碼省略***/ void setupSetterAndGetter(Object target) { mKeyframes.invalidateCache(); if (mProperty != null) { /***部分代碼省略***/ } // We can't just say 'else' here because the catch statement sets mProperty to null. if (mProperty == null) { Class targetClass = target.getClass(); if (mSetter == null) { //初始化mSetter setupSetter(targetClass); } /***部分代碼省略***/ } } //初始化mSetter用于以后反射執行get、set操作 void setupSetter(Class targetClass) { Class<?> propertyType = mConverter == null ? mValueType : mConverter.getTargetType(); mSetter = setupSetterOrGetter(targetClass, sSetterPropertyMap, "set", propertyType); } } ``` ### animation #### ValueAnimator.doAnimationFrame ``` public class ValueAnimator extends Animator { /***部分代碼省略***/ final boolean doAnimationFrame(long frameTime) { /***部分代碼省略***/ return animationFrame(currentTime); } boolean animationFrame(long currentTime) { boolean done = false; switch (mPlayingState) { case RUNNING: case SEEKED: /***部分代碼省略***/ if (fraction >= 1f) { //mCurrentIteration是否等于mRepeatCount if (mCurrentIteration < mRepeatCount || mRepeatCount == INFINITE) { // Time to repeat /***部分代碼省略***/ } else { //執行完這次,該動畫結束 done = true; fraction = Math.min(fraction, 1.0f); } } if (mPlayingBackwards) { fraction = 1f - fraction; } //設置View的屬性值 animateValue(fraction); break; } return done; } } ``` #### ValueAnimator.animateValue ``` public class ValueAnimator extends Animator { /***部分代碼省略***/ void animateValue(float fraction) { fraction = mInterpolator.getInterpolation(fraction); mCurrentFraction = fraction; int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { //PropertyValuesHolder.calculateValue就是計算每幀動畫所對應的值 mValues[i].calculateValue(fraction); } if (mUpdateListeners != null) { int numListeners = mUpdateListeners.size(); for (int i = 0; i < numListeners; ++i) { //屬性值得改變的回調 mUpdateListeners.get(i).onAnimationUpdate(this); } } } } ``` #### ObjectAnimator.animateValue ``` public final class ObjectAnimator extends ValueAnimator { /***部分代碼省略***/ @Override void animateValue(float fraction) { final Object target = getTarget(); if (mTarget != null && target == null) { // We lost the target reference, cancel and clean up. cancel(); return; } //ValueAnimator.animateValue方法 super.animateValue(fraction); int numValues = mValues.length; for (int i = 0; i < numValues; ++i) { //設置target的屬性值,進行View的移動,產生動畫 mValues[i].setAnimatedValue(target); } } } ``` ## PropertyValuesHolder > PropertyValuesHolder這個類的意義就是,它其中保存了動畫過程中所需要操作的屬性和對應的值。我們通過ofFloat(Object target, String propertyName, float… values)構造的動畫,ofFloat()的內部實現其實就是將傳進來的參數封裝成PropertyValuesHolder實例來保存動畫狀態。在封裝成PropertyValuesHolder實例以后,后期的各種操作也是以PropertyValuesHolder為主的。 ### ObjectAnimator.ofFloat 我們先看看我們之前的代碼中構造ObjectAnimator的方法: ``` public final class ObjectAnimator extends ValueAnimator { /***部分代碼省略***/ private ObjectAnimator(Object target, String propertyName) { setTarget(target); setPropertyName(propertyName); } public static ObjectAnimator ofFloat(Object target, String propertyName, float... values) { //構造ObjectAnimator ObjectAnimator anim = new ObjectAnimator(target, propertyName); anim.setFloatValues(values); return anim; } //設置屬性值 public void setPropertyName(@NonNull String propertyName) { /***部分代碼省略***/ mPropertyName = propertyName; // New property/values/target should cause re-initialization prior to starting mInitialized = false; } @Override public void setFloatValues(float... values) { if (mValues == null || mValues.length == 0) { // No values yet - this animator is being constructed piecemeal. Init the values with // whatever the current propertyName is if (mProperty != null) { setValues(PropertyValuesHolder.ofFloat(mProperty, values)); } else { setValues(PropertyValuesHolder.ofFloat(mPropertyName, values)); } } else { super.setFloatValues(values); } } } ``` ### 構造FloatPropertyValueHolder ``` public class PropertyValuesHolder implements Cloneable { /***部分代碼省略***/ public static PropertyValuesHolder ofFloat(String propertyName, float... values) { return new FloatPropertyValuesHolder(propertyName, values); } } ``` ``` public class PropertyValuesHolder implements Cloneable { /***部分代碼省略***/ static class FloatPropertyValuesHolder extends PropertyValuesHolder { public FloatPropertyValuesHolder(String propertyName, float... values) { super(propertyName); setFloatValues(values); } /***部分代碼省略***/ @Override public void setFloatValues(float... values) { super.setFloatValues(values); mFloatKeyframes = (Keyframes.FloatKeyframes) mKeyframes; } @Override void setAnimatedValue(Object target) { /***部分代碼省略***/ if (mSetter != null) { try { mTmpValueArray[0] = mFloatAnimatedValue; //反射操作target的屬性,通過set、get方法 mSetter.invoke(target, mTmpValueArray); } catch (InvocationTargetException e) { Log.e("PropertyValuesHolder", e.toString()); } catch (IllegalAccessException e) { Log.e("PropertyValuesHolder", e.toString()); } } } } } ``` ## 屬性動畫的內存泄露 - 上面講述到 `ValueAnimator.AnimationHandler.doAnimationFrame` 的時候說過,這個方法會循環執行。 - 因為 `ValueAnimator.AnimationHandler.doAnimationFrame` 每次執行完動畫(如果動畫沒有結束),都在再一次請求Vsync同步信號回調給自己。 - `Choreographer` 的回調都配post進入了當前線程的looper隊列中。 - `mRepeatCount` 無窮大,會導致該循環會一直執行下去,即使關閉當前的頁面也不會停止。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看