Animation之tween动画

来源:互联网 发布:dede模板下载站源码 编辑:程序博客网 时间:2024/05/21 20:21
从View的startAnimation来看动画执行流程;  /**     * Start the specified animation now.     *     * @param animation the animation to start now     */    public void startAnimation(Animation animation) {        animation.setStartTime(Animation.START_ON_FIRST_FRAME);        setAnimation(animation);        //更改父view去刷新缓存的标志位;       invalidateParentCaches();        //触发重新绘制事件;       invalidate(true);    }
  /**     * Used to indicate that the parent of this view should clear its caches. This functionality     * is used to force the parent to rebuild its display list (when hardware-accelerated),     * which is necessary when various parent-managed properties of the view change, such as     * alpha, translationX/Y, scrollX/Y, scaleX/Y, and rotation/X/Y. This method only     * clears the parent caches and does not causes an invalidate event.     *     * @hide     */           //英文已经说的很清楚了,这个是指示父view清除缓存;      protected void invalidateParentCaches() {        if (mParent instanceof View) {            ((View) mParent).mPrivateFlags |= PFLAG_INVALIDATED;        }    }
继续看刷新方法;   /**     * This is where the invalidate() work actually happens. A full invalidate()     * causes the drawing cache to be invalidated, but this function can be     * called with invalidateCache set to false to skip that invalidation step     * for cases that do not need it (for example, a component that remains at     * the same dimensions with the same content).     *     * @param invalidateCache Whether the drawing cache for this view should be     *            invalidated as well. This is usually true for a full     *            invalidate, but may be set to false if the View's contents or     *            dimensions have not changed.     */     //invalidateCache是false的时候, View的内容,大小没有改变的时候;      void invalidate(boolean invalidateCache) {        invalidateInternal(0, 0, mRight - mLeft, mBottom - mTop, invalidateCache, true);    }    void invalidateInternal(int l, int t, int r, int b, boolean invalidateCache,            boolean fullInvalidate) {        if (mGhostView != null) {            mGhostView.invalidate(true);            return;        }        //跳过刷新并且返回;这个是View不可见并且没有动画发生的时候;        if (skipInvalidate()) {            return;        }         //这个是要执行刷新的主要代码;        if ((mPrivateFlags & (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)) == (PFLAG_DRAWN | PFLAG_HAS_BOUNDS)                || (invalidateCache && (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID)                || (mPrivateFlags & PFLAG_INVALIDATED) != PFLAG_INVALIDATED                || (fullInvalidate && isOpaque() != mLastIsOpaque)) {            if (fullInvalidate) {                mLastIsOpaque = isOpaque();                mPrivateFlags &= ~PFLAG_DRAWN;            }            mPrivateFlags |= PFLAG_DIRTY;                         if (invalidateCache) {                mPrivateFlags |= PFLAG_INVALIDATED;                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;            }            // Propagate the damage rectangle to the parent view.            //翻译过来是把要修改的矩形区域传递给父view;           final AttachInfo ai = mAttachInfo;            final ViewParent p = mParent;            if (p != null && ai != null && l < r && t < b) {                final Rect damage = ai.mTmpInvalRect;                damage.set(l, t, r, b);                //父亲刷新子view的方法;跳转到它去看;               p.invalidateChild(this, damage);            }            // Damage the entire projection receiver, if necessary.            if (mBackground != null && mBackground.isProjected()) {                final View receiver = getProjectionReceiver();                if (receiver != null) {                    receiver.damageInParent();                }            }            // Damage the entire IsolatedZVolume receiving this view's shadow.            if (isHardwareAccelerated() && getZ() != 0) {                damageShadowReceiver();            }        }    }
ViewGroup中:

    /**     * Don't call or override this method. It is used for the implementation of     * the view hierarchy.     */        public final void invalidateChild(View child, final Rect dirty) {        ViewParent parent = this;        final AttachInfo attachInfo = mAttachInfo;        if (attachInfo != null) {            // If the child is drawing an animation, we want to copy this flag onto            // ourselves and the parent to make sure the invalidate request goes            // through           //翻译过来就是: 如果孩子有动画,就要把孩子的标志复制过来; 父亲确保刷新请求通过;            final boolean drawAnimation = (child.mPrivateFlags & PFLAG_DRAW_ANIMATION)                    == PFLAG_DRAW_ANIMATION;            // Check whether the child that requests the invalidate is fully opaque            // Views being animated or transformed are not considered opaque because we may            // be invalidating their old position and need the parent to paint behind them.            Matrix childMatrix = child.getMatrix();            final boolean isOpaque = child.isOpaque() && !drawAnimation &&                    child.getAnimation() == null && childMatrix.isIdentity();            // Mark the child as dirty, using the appropriate flag            // Make sure we do not set both flags at the same time            //设置正确的标志:只是dirty区域或者 dirty+opaue;           int opaqueFlag = isOpaque ? PFLAG_DIRTY_OPAQUE : PFLAG_DIRTY;            if (child.mLayerType != LAYER_TYPE_NONE) {                mPrivateFlags |= PFLAG_INVALIDATED;                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;            }            final int[] location = attachInfo.mInvalidateChildLocation;            location[CHILD_LEFT_INDEX] = child.mLeft;            location[CHILD_TOP_INDEX] = child.mTop;            //确定需要重新绘制的区域;           if (!childMatrix.isIdentity() ||                    (mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {                RectF boundingRect = attachInfo.mTmpTransformRect;                boundingRect.set(dirty);                Matrix transformMatrix;                if ((mGroupFlags & ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {                    Transformation t = attachInfo.mTmpTransformation;                    boolean transformed = getChildStaticTransformation(child, t);                    if (transformed) {                        transformMatrix = attachInfo.mTmpMatrix;                        transformMatrix.set(t.getMatrix());                        if (!childMatrix.isIdentity()) {                            transformMatrix.preConcat(childMatrix);                        }                    } else {                        transformMatrix = childMatrix;                    }                } else {                    transformMatrix = childMatrix;                }                transformMatrix.mapRect(boundingRect);                dirty.set((int) (boundingRect.left - 0.5f),                        (int) (boundingRect.top - 0.5f),                        (int) (boundingRect.right + 0.5f),                        (int) (boundingRect.bottom + 0.5f));            }            //这个是一个循环语句;主要作用是一直循环到ViewRootImpl,用它刷新dirty区域;            do {                View view = null;                if (parent instanceof View) {                    view = (View) parent;                }                if (drawAnimation) {                    if (view != null) {                        view.mPrivateFlags |= PFLAG_DRAW_ANIMATION;                    } else if (parent instanceof ViewRootImpl) {                        ((ViewRootImpl) parent).mIsAnimating = true;                    }                }                // If the parent is dirty opaque or not dirty, mark it dirty with the opaque                // flag coming from the child that initiated the invalidate                if (view != null) {                    if ((view.mViewFlags & FADING_EDGE_MASK) != 0 &&                            view.getSolidColor() == 0) {                        opaqueFlag = PFLAG_DIRTY;                    }                    if ((view.mPrivateFlags & PFLAG_DIRTY_MASK) != PFLAG_DIRTY) {                        view.mPrivateFlags = (view.mPrivateFlags & ~PFLAG_DIRTY_MASK) | opaqueFlag;                    }                }               // 作用是返回父view,并且确定脏区域; 跳转到它看具体代码; 然后看<pre name="code" class="java">               //   ViewRootImpl中的这个方法的调用;应该如何执行;
parent = parent.invalidateChildInParent(location, dirty); if (view != null) { // Account for transform on current parent Matrix m = view.getMatrix(); if (!m.isIdentity()) { RectF boundingRect = attachInfo.mTmpTransformRect; boundingRect.set(dirty); m.mapRect(boundingRect); dirty.set((int) (boundingRect.left - 0.5f), (int) (boundingRect.top - 0.5f), (int) (boundingRect.right + 0.5f), (int) (boundingRect.bottom + 0.5f)); } } } while (parent != null); } }
    /**     * Don't call or override this method. It is used for the implementation of     * the view hierarchy.     *     * This implementation returns null if this ViewGroup does not have a parent,     * if this ViewGroup is already fully invalidated or if the dirty rectangle     * does not intersect with this ViewGroup's bounds.     */    //解释: 如果ViewGroup没有父亲或者ViewGroup是已经全部刷新过了或者脏区域与当前ViewGroup范围没有交集,就会返回空;   public ViewParent invalidateChildInParent(final int[] location, final Rect dirty) {        if ((mPrivateFlags & PFLAG_DRAWN) == PFLAG_DRAWN ||                (mPrivateFlags & PFLAG_DRAWING_CACHE_VALID) == PFLAG_DRAWING_CACHE_VALID) {            if ((mGroupFlags & (FLAG_OPTIMIZE_INVALIDATE | FLAG_ANIMATION_DONE)) !=                        FLAG_OPTIMIZE_INVALIDATE) {                               //孩子的脏区域需要偏移到相对于父view的坐标区域;它是 孩子的mLeft+滚动的距离                dirty.offset(location[CHILD_LEFT_INDEX] - mScrollX,                        location[CHILD_TOP_INDEX] - mScrollY);                //如果不是只刷新孩子区域,则脏区域扩展到当前view; 默认是只刷新孩子区域的;               if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0) {                    dirty.union(0, 0, mRight - mLeft, mBottom - mTop);                }                final int left = mLeft;                final int top = mTop;                if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {                    if (!dirty.intersect(0, 0, mRight - left, mBottom - top)) {                        dirty.setEmpty();                    }                }                mPrivateFlags &= ~PFLAG_DRAWING_CACHE_VALID;                //当前位置变换成当前的ViewGroup的left,top, 因为循环后,当前View变成了孩子;                location[CHILD_LEFT_INDEX] = left;                location[CHILD_TOP_INDEX] = top;                if (mLayerType != LAYER_TYPE_NONE) {                    mPrivateFlags |= PFLAG_INVALIDATED;                }                return mParent;            } else {                mPrivateFlags &= ~PFLAG_DRAWN & ~PFLAG_DRAWING_CACHE_VALID;                location[CHILD_LEFT_INDEX] = mLeft;                location[CHILD_TOP_INDEX] = mTop;                if ((mGroupFlags & FLAG_CLIP_CHILDREN) == FLAG_CLIP_CHILDREN) {                    dirty.set(0, 0, mRight - mLeft, mBottom - mTop);                } else {                    // in case the dirty rect extends outside the bounds of this container                    dirty.union(0, 0, mRight - mLeft, mBottom - mTop);                }                if (mLayerType != LAYER_TYPE_NONE) {                    mPrivateFlags |= PFLAG_INVALIDATED;                }                return mParent;            }        }        return null;    }
ViewRootImpl:

  @Override    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {        checkThread();        if (DEBUG_DRAW) Log.v(TAG, "Invalidate child: " + dirty);        if (dirty == null) {            invalidate();            return null;        } else if (dirty.isEmpty() && !mIsAnimating) {            return null;        }        if (mCurScrollY != 0 || mTranslator != null) {            mTempRect.set(dirty);            dirty = mTempRect;            if (mCurScrollY != 0) {                dirty.offset(0, -mCurScrollY);            }            if (mTranslator != null) {                mTranslator.translateRectInAppWindowToScreen(dirty);            }            if (mAttachInfo.mScalingRequired) {                dirty.inset(-1, -1);            }        }        invalidateRectOnScreen(dirty);        return null;    }
把需要绘制的区域传递给了 invalidateRectOnScreen方法;

 private void invalidateRectOnScreen(Rect dirty) {        final Rect localDirty = mDirty;        if (!localDirty.isEmpty() && !localDirty.contains(dirty)) {            mAttachInfo.mSetIgnoreDirtyState = true;            mAttachInfo.mIgnoreDirtyState = true;        }        // Add the new dirty rect to the current one         //这个是把本地脏区域与dirty取并集,使新区域包含这两个区域;        localDirty.union(dirty.left, dirty.top, dirty.right, dirty.bottom);        // Intersect with the bounds of the window to skip        // updates that lie outside of the visible region        final float appScale = mAttachInfo.mApplicationScale;        final boolean intersected = localDirty.intersect(0, 0,                (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));        if (!intersected) {            localDirty.setEmpty();        }        //不是立即绘制,并且 区域有交集或者有动画的话,交给下面方法绘制;       if (!mWillDrawSoon && (intersected || mIsAnimating)) {            scheduleTraversals();        }    }



                                             
0 0
原创粉丝点击