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
- Animation之tween动画
- Android动画之Tween Animation
- Android动画之Tween Animation
- Android动画之Tween Animation
- Android动画之Tween Animation
- Animation---详解Android动画之Tween Animation
- Android动画之Tween Animation变化动画
- 详解Android动画之Tween Animation
- 详解Android动画之Tween Animation
- 详解Android动画之Tween Animation
- 详解Android动画之Tween Animation
- Android之Tween Animation动画详解
- 详解Android动画之Tween Animation
- 详解Android动画之Tween Animation
- 详解Android动画之Tween Animation
- 详解Android动画之Tween Animation
- Android--详解Android动画之Tween Animation
- 详解Android动画之Tween Animation
- 我的第一个安卓程序
- HashMap的遍历
- ZKoss树的一个例子
- Leetcode Largest Rectangle in Histogram
- 缓冲区概念
- Animation之tween动画
- python中的装饰器Decorator用法
- Linux文件编程综合(创建打开等)
- C语言32个关键字
- 刚刚开始学习编程
- 全局变量,局部变量和形式参数
- [1194]:Beat the Spread!
- 浮点数的比较
- C++有子对象的派生类的构造函数