�����ڵ�λ�ã���ҳ > ���� > Android���� > ����
AndroidӦ�ó��򴰿ڣ�Activity���IJ�����Measure�������֣�Layout���ͻ��ƣ�Draw�����̷���
http://www.drovik.com/      2013-2-1 15:27:51      ��Դ�����޵�Android֮��      �����
    �����������Ǿͼ�������FrameLayout�ij�Ա����draw��ʵ�֣��Ա�����˽�Ӧ�ó��򴰿�UI�Ļ��ƹ��̡�

       Step 7. FrameLayout.draw

  1. public class FrameLayout extends ViewGroup {  
  2.     ......  
  3.     
  4.     private Drawable mForeground;  
  5.     ......  
  6.   
  7.     public void draw(Canvas canvas) {  
  8.         super.draw(canvas);  
  9.   
  10.         if (mForeground != null) {  
  11.             final Drawable foreground = mForeground;  
  12.   
  13.             if (mForegroundBoundsChanged) {  
  14.                 mForegroundBoundsChanged = false;  
  15.                 final Rect selfBounds = mSelfBounds;  
  16.                 final Rect overlayBounds = mOverlayBounds;  
  17.   
  18.                 final int w = mRight-mLeft;  
  19.                 final int h = mBottom-mTop;  
  20.   
  21.                 if (mForegroundInPadding) {  
  22.                     selfBounds.set(00, w, h);  
  23.                 } else {  
  24.                     selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);  
  25.                 }  
  26.   
  27.                 Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),  
  28.                         foreground.getIntrinsicHeight(), selfBounds, overlayBounds);  
  29.                 foreground.setBounds(overlayBounds);  
  30.             }  
  31.   
  32.             foreground.draw(canvas);  
  33.         }  
  34.     }  
  35.   
  36.     ......  
  37. }  
public class FrameLayout extends ViewGroup { ...... private Drawable mForeground; ...... public void draw(Canvas canvas) { super.draw(canvas); if (mForeground != null) { final Drawable foreground = mForeground; if (mForegroundBoundsChanged) { mForegroundBoundsChanged = false; final Rect selfBounds = mSelfBounds; final Rect overlayBounds = mOverlayBounds; final int w = mRight-mLeft; final int h = mBottom-mTop; if (mForegroundInPadding) { selfBounds.set(0, 0, w, h); } else { selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom); } Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(), foreground.getIntrinsicHeight(), selfBounds, overlayBounds); foreground.setBounds(overlayBounds); } foreground.draw(canvas); } } ...... }

        ��������������ļ�frameworks/base/core/java/android/widget/FrameLayout.java�С�

        FrameLayout��ij�Ա����draw���ȵ��ø���View�ij�Ա����draw����������UI���ݣ�Ȼ���ټ�����Ƿ�������һ��ǰ��ͼ������Ա����mForeground��ֵ�Ƿ����null�����������null�Ļ�����ô�ͻ����������ǰ��ͼ�Ĵ�С��λ�ã�Ȼ���ٵ����ó�Ա����mForeground��ָ���һ��Drawable����ij�Ա����draw���ڻ���canvas�ϻ������ǰ��ͼ��

        �����������Ǿͼ�������View��ij�Ա����draw��ʵ�֣��Ա�����˽�Ӧ�ó��򴰿�UI�Ļ��ƹ��̡�

        Step 8. View.draw

        ��������������ļ�frameworks/base/core/java/android/view/View.java�У�����Ҫ�������������������

        1. ���Ƶ�ǰ��ͼ�ı�����

        2. ���浱ǰ�����Ķ�ջ״̬���������ڵ�ǰ�����ϴ��������ͼ�㣬�Ա�����������������Ƶ�ǰ��ͼ�ڻ���ʱ�ı߿򽥱�Ч����

        3. ���Ƶ�ǰ��ͼ�����ݡ�

        4. ���Ƶ�ǰ��ͼ������ͼ�����ݡ�

        5. ���Ƶ�ǰ��ͼ�ڻ���ʱ�ı߿򽥱�Ч����

        6. ���Ƶ�ǰ��ͼ�Ĺ�������

        ���������������У���Щ�ǿ����Ż��ġ����磬�����ǰ��ͼ��ijһ������ͼ�Dz�͸���ģ����Ҹ����˵�ǰ��ͼ�����ݣ���ô��ǰ��ͼ�ı����Լ����ݾͲ�������ˣ�������ִ�е�1�͵�3�����������磬�����ǰ��ͼ���Ǵ��ڻ�����״̬����ô��2�͵�5������Ҳ�Dz���ִ�еġ�

        ���������Ǿͷֶ����Ķ�View��ij�Ա����draw�Ĵ��룺

  1. public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource {  
  2.     ......  
  3.   
  4.     public void draw(Canvas canvas) {  
  5.         ......  
  6.   
  7.         final int privateFlags = mPrivateFlags;  
  8.         final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE &&  
  9.                 (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);  
  10.         mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;  
public class View implements Drawable.Callback, KeyEvent.Callback, AccessibilityEventSource { ...... public void draw(Canvas canvas) { ...... final int privateFlags = mPrivateFlags; final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE && (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN;        ��δ�����View��ij�Ա����mPrivateFlags��DIRTY_OPAQUEλ�Ƿ����1���������1�Ļ�����ô��˵����ǰ��ͼ��ijһ������ͼ������һ����͸��UI���Ʋ���������������£���ǰ��ͼ�ᱻ����ͼ���ǣ���ˣ��Ͳ���Ҫִ��ǰ����˵�ĵ�1�͵�3�������ˡ�����������ִ�е�1�͵�3����������һ��ǰ�ᣬ�Ǿ���View��ij�Ա����mAttachInfo��ָ���һ��AttachInfo����ij�Ա����mIgnoreDirtyState��ֵ����false�����ʾ��ǰ��ͼ�����Ժ��Գ�Ա����mPrivateFlags��DIRTY_OPAQUEλ��������������������֮�󣬱���dirtyOpaque��ֵ�ͻ����true��

         View��ij�Ա�����ڼ�������ִ��֮ǰ�����Ὣ��Ա����mPrivateFlags��DIRTY_MASKλ����Ϊ0���Լ���DRAWNλ����Ϊ1����Ϊ��������Ҫ��ʼ���Ƶ�ǰ��ͼ��UI�ˡ�

         ���Ǽ��������Ķ����룺

  1. // Step 1, draw the background, if needed  
  2. int saveCount;  
  3.   
  4. if (!dirtyOpaque) {  
  5.     final Drawable background = mBGDrawable;  
  6.     if (background != null) {  
  7.         final int scrollX = mScrollX;  
  8.         final int scrollY = mScrollY;  
  9.   
  10.         if (mBackgroundSizeChanged) {  
  11.             background.setBounds(00,  mRight - mLeft, mBottom - mTop);  
  12.             mBackgroundSizeChanged = false;  
  13.         }  
  14.   
  15.         if ((scrollX | scrollY) == 0) {  
  16.             background.draw(canvas);  
  17.         } else {  
  18.             canvas.translate(scrollX, scrollY);  
  19.             background.draw(canvas);  
  20.             canvas.translate(-scrollX, -scrollY);  
  21.         }  
  22.     }  
  23. }  
// Step 1, draw the background, if needed int saveCount; if (!dirtyOpaque) { final Drawable background = mBGDrawable; if (background != null) { final int scrollX = mScrollX; final int scrollY = mScrollY; if (mBackgroundSizeChanged) { background.setBounds(0, 0, mRight - mLeft, mBottom - mTop); mBackgroundSizeChanged = false; } if ((scrollX | scrollY) == 0) { background.draw(canvas); } else { canvas.translate(scrollX, scrollY); background.draw(canvas); canvas.translate(-scrollX, -scrollY); } } }        ��δ�������ִ�������ĵ�1��������������ֻ�����dirtyOpaque��ֵ����false������²Ż�ִ�С���ǰ��ͼ�ı�����ͨ����Ա����mBGDrawable��ָ���һ��Drawable�����������ġ��ڻ��Ƶ�ǰ��ͼ�ı���֮ǰ���������������Ĵ�С��λ�á�

        ���Ǽ��������Ķ����룺

  1. // skip step 2 & 5 if possible (common case)  
  2. final int viewFlags = mViewFlags;  
  3. boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0;  
  4. boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0;  
  5. if (!verticalEdges && !horizontalEdges) {  
  6.     // Step 3, draw the content  
  7.     if (!dirtyOpaque) onDraw(canvas);  
  8.   
  9.     // Step 4, draw the children  
  10.     dispatchDraw(canvas);  
  11.   
  12.     // Step 6, draw decorations (scrollbars)  
  13.     onDrawScrollBars(canvas);  
  14.   
  15.     // we're done...  
  16.     return;  
  17. }  
// skip step 2 & 5 if possible (common case) final int viewFlags = mViewFlags; boolean horizontalEdges = (viewFlags & FADING_EDGE_HORIZONTAL) != 0; boolean verticalEdges = (viewFlags & FADING_EDGE_VERTICAL) != 0; if (!verticalEdges && !horizontalEdges) { // Step 3, draw the content if (!dirtyOpaque) onDraw(canvas); // Step 4, draw the children dispatchDraw(canvas); // Step 6, draw decorations (scrollbars) onDrawScrollBars(canvas); // we're done... return; }

       ��δ������Ƿ�������������ĵ�2�͵�5����������View��ij�Ա����mViewFlags��FADING_EDGE_HORIZONTALλ����1��ʱ�򣬾�˵����ǰ��ͼ���ڴ���ˮƽ����״̬��������Ҫ����ˮƽ�߿�Ľ���Ч����ͬ������View��ij�Ա����mViewFlags��FADING_EDGE_VERTICALλ����1��ʱ�򣬾�˵����ǰ��ͼ���ڴ��ڴ�ֱ����״̬��������Ҫ���ƴ�ֱ�߿�Ľ���Ч�������ǣ������ǰ��ͼ���Ǵ��ڻ���״̬��������horizontalEdges��verticalEdges��ֵ������false��ʱ����ô�Ͳ���Ҫִ�������ĵ�2�͵�5�������ˣ���ֻ��Ҫִ�е�3����4�͵�6��������ע�⣬������dirtyOpaque��ֵ����true��ʱ�򣬵�3������Ҳ�Dz���Ҫִ�еġ�

        ���Ǽ������·������룺

  1. boolean drawTop = false;  
  2. boolean drawBottom = false;  
  3. boolean drawLeft = false;  
  4. boolean drawRight = false;  
  5.   
  6. float topFadeStrength = 0.0f;  
  7. float bottomFadeStrength = 0.0f;  
  8. float leftFadeStrength = 0.0f;  
  9. float rightFadeStrength = 0.0f;  
  10.   
  11. // Step 2, save the canvas' layers  
  12. int paddingLeft = mPaddingLeft;  
  13. int paddingTop = mPaddingTop;  
  14.   
  15. final boolean offsetRequired = isPaddingOffsetRequired();  
  16. if (offsetRequired) {  
  17.     paddingLeft += getLeftPaddingOffset();  
  18.     paddingTop += getTopPaddingOffset();  
  19. }  
  20.   
  21. int left = mScrollX + paddingLeft;  
  22. int right = left + mRight - mLeft - mPaddingRight - paddingLeft;  
  23. int top = mScrollY + paddingTop;  
  24. int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop;  
  25.   
  26. if (offsetRequired) {  
  27.     right += getRightPaddingOffset();  
  28.     bottom += getBottomPaddingOffset();  
  29. }  
  30.   
  31. final ScrollabilityCache scrollabilityCache = mScrollCache;  
  32. int length = scrollabilityCache.fadingEdgeLength;  
  33.   
  34. // clip the fade length if top and bottom fades overlap  
  35. // overlapping fades produce odd-looking artifacts  
  36. if (verticalEdges && (top + length > bottom - length)) {  
  37.     length = (bottom - top) / 2;  
  38. }  
  39.   
  40. // also clip horizontal fades if necessary  
  41. if (horizontalEdges && (left + length > right - length)) {  
  42.     length = (right - left) / 2;  
  43. }  
  44.   
  45. if (verticalEdges) {  
  46.     topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength()));  
  47.     drawTop = topFadeStrength >= 0.0f;  
  48.     bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength()));  
  49.     drawBottom = bottomFadeStrength >= 0.0f;  
  50. }  
  51.   
  52. if (horizontalEdges) {  
  53.     leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength()));  
  54.     drawLeft = leftFadeStrength >= 0.0f;  
  55.     rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength()));  
  56.     drawRight = rightFadeStrength >= 0.0f;  
  57. }  
  58.   
  59. saveCount = canvas.getSaveCount();  
  60.   
  61. int solidColor = getSolidColor();  
  62. if (solidColor == 0) {  
  63.     final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG;  
  64.   
  65.     if (drawTop) {  
  66.         canvas.saveLayer(left, top, right, top + length, null, flags);  
  67.     }  
  68.   
  69.     if (drawBottom) {  
  70.         canvas.saveLayer(left, bottom - length, right, bottom, null, flags);  
  71.     }  
  72.   
  73.     if (drawLeft) {  
  74.         canvas.saveLayer(left, top, left + length, bottom, null, flags);  
  75.     }  
  76.   
  77.     if (drawRight) {  
  78.         canvas.saveLayer(right - length, top, right, bottom, null, flags);  
  79.     }  
  80. else {  
  81.     scrollabilityCache.setFadeColor(solidColor);  
  82. }  
boolean drawTop = false; boolean drawBottom = false; boolean drawLeft = false; boolean drawRight = false; float topFadeStrength = 0.0f; float bottomFadeStrength = 0.0f; float leftFadeStrength = 0.0f; float rightFadeStrength = 0.0f; // Step 2, save the canvas' layers int paddingLeft = mPaddingLeft; int paddingTop = mPaddingTop; final boolean offsetRequired = isPaddingOffsetRequired(); if (offsetRequired) { paddingLeft += getLeftPaddingOffset(); paddingTop += getTopPaddingOffset(); } int left = mScrollX + paddingLeft; int right = left + mRight - mLeft - mPaddingRight - paddingLeft; int top = mScrollY + paddingTop; int bottom = top + mBottom - mTop - mPaddingBottom - paddingTop; if (offsetRequired) { right += getRightPaddingOffset(); bottom += getBottomPaddingOffset(); } final ScrollabilityCache scrollabilityCache = mScrollCache; int length = scrollabilityCache.fadingEdgeLength; // clip the fade length if top and bottom fades overlap // overlapping fades produce odd-looking artifacts if (verticalEdges && (top + length > bottom - length)) { length = (bottom - top) / 2; } // also clip horizontal fades if necessary if (horizontalEdges && (left + length > right - length)) { length = (right - left) / 2; } if (verticalEdges) { topFadeStrength = Math.max(0.0f, Math.min(1.0f, getTopFadingEdgeStrength())); drawTop = topFadeStrength >= 0.0f; bottomFadeStrength = Math.max(0.0f, Math.min(1.0f, getBottomFadingEdgeStrength())); drawBottom = bottomFadeStrength >= 0.0f; } if (horizontalEdges) { leftFadeStrength = Math.max(0.0f, Math.min(1.0f, getLeftFadingEdgeStrength())); drawLeft = leftFadeStrength >= 0.0f; rightFadeStrength = Math.max(0.0f, Math.min(1.0f, getRightFadingEdgeStrength())); drawRight = rightFadeStrength >= 0.0f; } saveCount = canvas.getSaveCount(); int solidColor = getSolidColor(); if (solidColor == 0) { final int flags = Canvas.HAS_ALPHA_LAYER_SAVE_FLAG; if (drawTop) { canvas.saveLayer(left, top, right, top + length, null, flags); } if (drawBottom) { canvas.saveLayer(left, bottom - length, right, bottom, null, flags); } if (drawLeft) { canvas.saveLayer(left, top, left + length, bottom, null, flags); } if (drawRight) { canvas.saveLayer(right - length, top, right, bottom, null, flags); } } else { scrollabilityCache.setFadeColor(solidColor); }        ��δ�����������Ƿ���Ҫ�������canvas��������һ�黭���Ķ�ջ״̬�����Ҵ��������ͼ�������Ƶ�ǰ��ͼ�ڻ���ʱ�ı߿򽥱�Ч������ͼ�ı߿��ǻ�������������ı߽�λ���ϵģ�����ͼ��������������Ҫ�ų���Ա����mPaddingLeft��mPaddingRight��mPaddingTop��mPaddingBottom����������ͼ�ڱ߾�ġ����⣬��ͼ�ı߿����ĸ����ֱ�λ����ͼ�����ҡ����Լ����ڱ߽��ϡ���ˣ���δ���������Ҫ�������ǰ��ͼ�����ҡ����Լ����ڱ߾�Ĵ�С���Ա�õ��߿���Ҫ���Ƶ�����

        ����ͨ��View��ij�Ա����mPaddingLeft��mPaddingRight��mPaddingTop��mPaddingBottom�Ϳ��Եõ�����ͼ�����ҡ����Լ����ڱ߾�Ĵ�С�ģ�������ʱ�������ڶ���һ����ͼ��ʱ�򣬿��ܻ���Ҫ����ͼ���ڱ߾��ϻ�����������Ķ�������ʱ�������չ��ͼ���ڱ߾�������������չ��ͼ���ڱ߾��������ô����Ҫ��дView��ij�Ա����isPaddingOffsetRequired���������ķ���ֵ����Ϊtrue���������������ĸ���Ա����getLeftPaddingOffset��getRightPaddingOffset��getTopPaddingOffset��getBottomPaddingOffset���ṩ��������ҡ����Լ����ڱ߾ࡣ

       ��δ��뾭������󣬾͵õ��ĸ�ֵleft��right��top��bottom�����Ƿֱ��ʾ��ǰ��ͼ�����������Ƶ�����������������Ѿ������õĺ���չ���ڱ߾��ų�֮�⡣

       �����left��right��top��bottom���ĸ�ֵ֮�󣬾��൱�ڵõ����ҡ����Լ��±߿����ʼλ���ˣ������һ���Ҫ֪���߿�ij��ȣ�����ȷ�����ҡ����Լ��±߿���Ҫ���Ƶ�����

       �߿�ij���length������View��ij�Ա����mScrollCache��ָ���һ��ScrollabilityCache����ij�Ա����fadingEdgeLength�С����ǣ����Ԥ�����õı߿򳤶�length��һ���ʺϵ�ǰ��ͼʹ�á�������Ϊ��ͼ�Ĵ�С�ǿ�����ʱ�ı�ģ�һ�������˸ı�֮��ԭ�����õı߿򳤶�length���ܾͻ��Եù�����������˵�����ǵ����������߿�������������߿����ص�ʱ����˵��ԭ�����õı߿򳤶ȹ����ˡ�����������£���Ҫ���߿򳤶�length�޸�Ϊ��ǰ��ͼ����������ĸ߶ȺͿ��ȵĽ�С�ߵ�һ�룬�Ա���Ա�֤���������߿�������������߿򲻻ᷢ���ص���

       ���ҡ����Լ��±߿򶼶�Ӧ��һ��ǿ��ֵ��ǿ��ֵ��ȡֵ��ΧΪ[0.0, 1.0]�����һ���߿��ǿ��ֵ����0.0����ô�����Dz��ɼ��ģ���ʱ��Ͳ���Ҫ�������Ľ���Ч������һ���棬���һ���߿��ǿ��ֵ����1.0����ô���ij��ȵ���ԭ�����õij��ȡ����ǿ��Խ����ǿ��ֵ����Ϊһ���������ӡ����ҡ����Լ��±߿��ǿ��ֵ���Էֱ�ͨ������View��ij�Ա����getLeftFadingEdgeStrength��getRightFadingEdgeStrength��getTopFadingEdgeStrength�Լ�getBottomFadingEdgeStrength����á�ע�⣬ֻ���ڱ���verticalEdges��ֵ����true��ʱ����δ���Ż�������������߿��ǿ��ֵtopFadeStrength��bottomFadeStrength��ͬ����ֻ�б���horizontalEdges��ֵ����true��ʱ�������Ż�������������߿��ǿ��ֵleftFadeStrength��rightFadeStrength�� 

        ��������ҡ����Լ��±߿��ǿ��ֵleftFadeStrength��rightFadeStrength��topFadeStrength�Լ�bottomFadeStrength֮����δ���ͻ��ж����ǵ�ֵ�Ƿ����0���������0����ô����������Ӧ���ĸ�����drawLeft��drawRight��drawTop�Լ�drawBottom��ֵ�ͻ����true����ʾ��Ҫ�������ҡ����Լ����ĸ��߿�Ľ���Ч����

        View��ij�Ա����getSolidColor���ص��ǵ�ǰ��ͼ�ı�����ɫ�������ǰ��ͼ�ı�����ɫ�Ǵ�ɫ�ģ�������solidColor��ֵ������0����ô��ʱ��ͻ�ʹ�����������ɫ�����Ʊ߿�Ľ���Ч���������ñ���scrollabilityCache��ָ���һ��ScrollabilityCache����ij�Ա����setFadeColor�������߿�Ľ���Ч����ɫ����ΪsolidColor����������DZȽϼ򵥵ġ������ǰ��ͼ�ı�����ɫ���Ǵ�ɫ�ģ�������solidColor��ֵ����0����������ͱȽϸ����ˣ�������Ҫ�����ڲ���canvas��������һ�黭���������������ͼ�������Ʊ߿�Ľ���Ч������������Ϊ���ܹ�ʹ�ñ�����ɫ�����Ʊ߿�Ľ���Ч����

        ����canvas��������һ�黭���������������ͼ����ͨ���������ij�Ա����saveLayer��ʵ�ֵġ�����ע�⵽�ڵ��ò���canvas��ָ���һ��Canvas����ij�Ա����saveLayer��ʱ�����һ������ָ��ΪCanvas.HAS_ALPHA_LAYER_SAVE_FLAG�����ʾ�ڽ����ⴴ����ͼ��ϳɵ�����canvas��������һ�黭����ȥ��Ҫ�����ⴴ����ͼ������һ��͸����ֵ��ͬʱ�����ǻ����Կ�������ǰ��ͼ�����ҡ��Ϻ��±߿���ռ�ݵķ�Χ�ֱ�Ϊ��left, top, left + length, bottom������right - length, top, right, bottom������left, top, right, top + length���ͣ�left, bottom - length, right, bottom������������һ���ط���Ҫע����ǣ��ڲ���canvas��������һ�黭���������������ͼ��֮ǰ����δ������Ȼ��û����ĵ�ǰ��ջ״̬������ͨ��һ������saveCount�������ģ��������������ͨ�����ò���canvas��ָ���һ��Canvas����ij�Ա����getSaveCount����õġ������������ڶ��ⴴ����ͼ���ϻ����˱߿�Ľ���Ч��֮�󣬾Ϳ���ͨ��ǰ��õ�������saveCount���ָ������Ķ�ջ״̬��Ҳ���ǽ�ǰ����ⴴ����ͼ��ϳɵ�����������

        ���ǽ��������Ķ����룺

  1. // Step 3, draw the content  
  2. if (!dirtyOpaque) onDraw(canvas);  
  3.   
  4. // Step 4, draw the children  
  5. dispatchDraw(canvas);  
// Step 3, draw the content if (!dirtyOpaque) onDraw(canvas); // Step 4, draw the children dispatchDraw(canvas);

       ��δ�������ִ�������ĵ�3�͵�4�������������Ƶ�ǰ��ͼ�����ݣ��Լ���ǰ��ͼ������ͼ�����ݣ����Ƿֱ���ͨ������View��ij�Ա����onDraw��dispatchDraw��ʵ�ֵġ�������Ҫ��ע��ǰ��ͼ������ͼ�Ļ��ƹ��̣���ˣ��ڽ�������Step 9�У���������ϸ����View��ij�Ա����dispatchDraw��ʵ�֡�

       ���ǽ��������Ķ����룺

  1.  // Step 5, draw the fade effect and restore layers  
  2.  final Paint p = scrollabilityCache.paint;  
  3.  final Matrix matrix = scrollabilityCache.matrix;  
  4.  final Shader fade = scrollabilityCache.shader;  
  5.  final float fadeHeight = scrollabilityCache.fadingEdgeLength;  
  6.   
  7.  if (drawTop) {  
  8.      matrix.setScale(1, fadeHeight * topFadeStrength);  
  9.      matrix.postTranslate(left, top);  
  10.      fade.setLocalMatrix(matrix);  
  11.      canvas.drawRect(left, top, right, top + length, p);  
  12.  }  
  13.   
  14.  if (drawBottom) {  
  15.      matrix.setScale(1, fadeHeight * bottomFadeStrength);  
  16.      matrix.postRotate(180);  
  17.      matrix.postTranslate(left, bottom);  
  18.      fade.setLocalMatrix(matrix);  
  19.      canvas.drawRect(left, bottom - length, right, bottom, p);  
  20.  }  
  21.   
  22.  if (drawLeft) {  
  23.      matrix.setScale(1, fadeHeight * leftFadeStrength);  
  24.      matrix.postRotate(-90);  
  25.      matrix.postTranslate(left, top);  
  26.      fade.setLocalMatrix(matrix);  
  27.      canvas.drawRect(left, top, left + length, bottom, p);  
  28.  }  
  29.   
  30.  if (drawRight) {  
  31.      matrix.setScale(1, fadeHeight * rightFadeStrength);  
  32.      matrix.postRotate(90);  
  33.      matrix.postTranslate(right, top);  
  34.      fade.setLocalMatrix(matrix);  
  35.      canvas.drawRect(right - length, top, right, bottom, p);  
  36.  }  
  37.   
  38. canvas.restoreToCount(saveCount);  
// Step 5, draw the fade effect and restore layers final Paint p = scrollabilityCache.paint; final Matrix matrix = scrollabilityCache.matrix; final Shader fade = scrollabilityCache.shader; final float fadeHeight = scrollabilityCache.fadingEdgeLength; if (drawTop) { matrix.setScale(1, fadeHeight * topFadeStrength); matrix.postTranslate(left, top); fade.setLocalMatrix(matrix); canvas.drawRect(left, top, right, top + length, p); } if (drawBottom) { matrix.setScale(1, fadeHeight * bottomFadeStrength); matrix.postRotate(180); matrix.postTranslate(left, bottom); fade.setLocalMatrix(matrix); canvas.drawRect(left, bottom - length, right, bottom, p); } if (drawLeft) { matrix.setScale(1, fadeHeight * leftFadeStrength); matrix.postRotate(-90); matrix.postTranslate(left, top); fade.setLocalMatrix(matrix); canvas.drawRect(left, top, left + length, bottom, p); } if (drawRight) { matrix.setScale(1, fadeHeight * rightFadeStrength); matrix.postRotate(90); matrix.postTranslate(right, top); fade.setLocalMatrix(matrix); canvas.drawRect(right - length, top, right, bottom, p); } canvas.restoreToCount(saveCount);        ��δ������������Ƶ�ǰ��ͼ�����ҡ����Լ��±߿�Ľ���Ч����ע�⣬ֻ�����ҡ����Լ��±߿�����Ӧ���ĸ�����drawLeft��drawRight��drawTop�Լ�drawBottom��ֵ����trueʱ�����ҡ����Լ��±߿�Ľ���Ч������Ҫ���ơ�ͬʱ�����ҡ����Լ��±߿��ڻ��Ƶ�ʱ�򣬶��ᱻ����һ���������ӣ���ǰ�����õ������ҡ����Լ��±߿��ǿ��ֵleftFadeStrength��rightFadeStrength��topFadeStrength�Լ�bottomFadeStrength��

        ���ڵ�ǰ��ͼ�����ҡ����Լ��±߿�Ľ���Ч�����ڲ���canvas��������һ�黭���Ķ��ⴴ����ͼ���ϻ��Ƶģ���ˣ��ڻ�����֮����δ�����Ҫ���ò���canvas��ָ���һ��Canvas�������ָ�����canvas��������һ�黭���ڴ�������ͼ��ʱ�Ķ�ջ״̬�����൱���ǽ�ǰ�������Ƶı߿򽥱�Ч���ϳɵ�����canvas��������һ�黭������

        ���Ǽ��������Ķ����һ�δ��룺

  1.         // Step 6, draw decorations (scrollbars)  
  2.         onDrawScrollBars(canvas);  
  3.     }  
  4.   
  5.     ......  
  6. }  
// Step 6, draw decorations (scrollbars) onDrawScrollBars(canvas); } ...... }       ��δ�������ִ�������ĵ�6��������������View��ij�Ա����onDrawScrollBars�����Ƶ�ǰ��ͼ�Ĺ�������

       �����������Ǿ���Ҫ��ע��ǰ��ͼ������ͼ�Ļ��ƹ��̣���View��ij�Ա����dispatchDraw��ʵ�֡�ע�⣬View��ij�Ա����dispatchDraw��һ����ʵ�֣�����������ViewGroup����д�ģ�Ҳ����˵��ֻ�е�һ����ͼ��������һ����ͼ����ʱ�����Ż���д����View�ij�Ա����dispatchDraw��

       ǰ�������Ѿ����赱ǰ���ڴ�������ͼ��Ӧ�ó��򴰿ڵĶ�����ͼ��������һ������ΪDecorView��ͼ��DecorView���Ǵ�ViewGroup��̳������ģ�������ViewGroup������д�˸���View��ij�Ա����dispatchDraw����ˣ����������Ǿͼ�������ViewGroup�ij�Ա����dispatchDraw��ʵ�֡�

       Step 9. ViewGroup.dispatchDraw

       ��������������ļ�frameworks/base/core/java/android/view/ViewGroup.java�У�����ʵ�ֱȽϳ������Ƿֶ����Ķ���

  1. public abstract class ViewGroup extends View implements ViewParent, ViewManager {  
  2.     ......  
  3.   
  4.     @Override  
  5.     protected void dispatchDraw(Canvas canvas) {  
  6.         final int count = mChildrenCount;  
  7.         final View[] children = mChildren;  
  8.         int flags = mGroupFlags;  
public abstract class ViewGroup extends View implements ViewParent, ViewManager { ...... @Override protected void dispatchDraw(Canvas canvas) { final int count = mChildrenCount; final View[] children = mChildren; int flags = mGroupFlags;       ViewGroup��ij�Ա����mChildrenCount�������ǵ�ǰ��ͼ�������ͼ�ĸ���������һ����Ա����mChildren��һ������ΪView�����飬�������浱ǰ��ͼ�������ͼ�����⣬ViewGroup��ij�Ա����mGroupFlags����������ǰ��ͼ��ı�־λ����δ��뽫����ViewGroup���������Ա�����ֱ𱣴��ڱ���count��children��flags�У��Ա���������Է��ʡ�

       ���Ǽ��������Ķ����룺

  1. if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) {  
  2.     ......  
  3.   
  4.     for (int i = 0; i < count; i++) {  
  5.         final View child = children[i];  
  6.         if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) {  
  7.             ......  
  8.             bindLayoutAnimation(child);  
  9.             ......  
  10.         }  
  11.     }  
  12.   
  13.     final LayoutAnimationController controller = mLayoutAnimationController;  
  14.     ......  
  15.   
  16.     controller.start();  
  17.   
  18.     ......  
  19.   
  20.     if (mAnimationListener != null) {  
  21.         mAnimationListener.onAnimationStart(controller.getAnimation());  
  22.     }  
  23. }  
if ((flags & FLAG_RUN_ANIMATION) != 0 && canAnimate()) { ...... for (int i = 0; i < count; i++) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE) { ...... bindLayoutAnimation(child); ...... } } final LayoutAnimationController controller = mLayoutAnimationController; ...... controller.start(); ...... if (mAnimationListener != null) { mAnimationListener.onAnimationStart(controller.getAnimation()); } }

        ��δ���������鵱ǰ��ͼ�������ͼ�Ƿ���Ҫ��ʾ�������������flags��FLAG_RUN_ANIMATIONλ����1������ViewGroup��ij�Ա����canAnimate�ķ���ֵ����true������ǰ��ǰ��ͼ������������ͼ��ʾ��������ô��δ����������Ҫ��ʼ��ʾ�����ˡ�

        ��δ������ȼ�鵱ǰ��ͼ���ÿһ������ͼchild��������ǿɼ��ģ���ô�ͻ����ViewGroup�������һ����Ա����bindLayoutAnimation���������Ķ����������������ͼ�Ķ���֮����δ���������ٵ���ViewGroup��ij�Ա����mLayoutAnimationController��ָ���һ��LayoutAnimationController����ij�Ա����start���������������ҵ���ViewGroup��ij�Ա����mAnimationListener��ָ���һ��AnimationListener����ij�Ա����onAnimationStart��֪ͨ��Щע�ᵽ��ǰ��ͼ��Ķ��������ߣ���ǰ��ͼ�鿪ʼ��ʾ�����ˡ�

        ���Ǽ��������Ķ����룺

  1. int saveCount = 0;  
  2. final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK;  
  3. if (clipToPadding) {  
  4.     saveCount = canvas.save();  
  5.     canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop,  
  6.             mScrollX + mRight - mLeft - mPaddingRight,  
  7.             mScrollY + mBottom - mTop - mPaddingBottom);  
  8.   
  9. }  
int saveCount = 0; final boolean clipToPadding = (flags & CLIP_TO_PADDING_MASK) == CLIP_TO_PADDING_MASK; if (clipToPadding) { saveCount = canvas.save(); canvas.clipRect(mScrollX + mPaddingLeft, mScrollY + mPaddingTop, mScrollX + mRight - mLeft - mPaddingRight, mScrollY + mBottom - mTop - mPaddingBottom); }        ��δ��������flags��CLIP_TO_PADDING_MASKλ�Ƿ񲻵���1�����������1�Ļ�����ô��˵����Ҫ���ò���canvas��������һ�黭���ļ�������ʹ������ü����򲻰�����ǰ��ͼ����ڱ߾ࡣע�⣬��ǰ��ͼ����ڱ߾���ͨ���Ӹ���View�̳��������ĸ���Ա����mPaddingLeft��mPaddingRight��mPaddingTop��mPaddingBottom�������ġ����⣬��ǰ��ͼ���������ͨ���Ӹ���̳��������ĸ���Ա������mLeft��mRight��mTop��mBottom�����ġ��ٽ�ϵ�ǰ��ͼ�ĵ�ǰ����λ��mScrollX��mScrollY���Ϳ��Լ��������canvas��������һ�黭���ļ�������

        �����ò���canvas��������һ�黭���ļ�������֮ǰ����δ�����ȵ��ò���canvas��ָ���һ��Canvas����ij�Ա����save���������Ķ�ջ״̬���Ա��ڻ�����ɵ�ǰ��ͼ���UI֮�󣬿��Իָ�canvas��������һ�黭���Ķ�ջ״̬��

        ���Ǽ��������Ķ����룺

  1. boolean more = false;  
  2. final long drawingTime = getDrawingTime();  
  3.   
  4. if ((flags & FLAG_USE_CHILD_DRAWING_ORDER) == 0) {  
  5.     for (int i = 0; i < count; i++) {  
  6.         final View child = children[i];  
  7.         if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {  
  8.             more |= drawChild(canvas, child, drawingTime);  
  9.         }  
  10.     }  
  11. else {  
  12.     for (int i = 0; i < count; i++) {  
  13.         final View child = children[getChildDrawingOrder(count, i)];  
  14.         if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {  
  15.             more |= drawChild(canvas, child, drawingTime);  
  16.         }  
  17.     }  
  18. }  
boolean more = false; final long drawingTime = getDrawingTime(); if ((flags & FLAG_USE_CHILD_DRAWING_ORDER) == 0) { for (int i = 0; i < count; i++) { final View child = children[i]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { more |= drawChild(canvas, child, drawingTime); } } } else { for (int i = 0; i < count; i++) { final View child = children[getChildDrawingOrder(count, i)]; if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) { more |= drawChild(canvas, child, drawingTime); } } }       ��δ����������Ƶ�ǰ��ͼ�������ͼ�����һ������ͼchild�ǿɼ��ģ������ij�Ա����mViewFlags��VISIBLEλ����1����������һ��������Ҫ��ʾ�������ij�Ա����getAnimation�ķ���ֵ������null����ô�������ͼ������Ҫ���Ƶġ�����һ������ͼ��ͨ������ViewGroup��ij�Ա����drawChild��ʵ�ֵġ�ViewGroup��ij�Ա����drawChild�ڻ���һ������ͼ��ʱ������������ͼ�Ķ�����û�н�������ô���ķ���ֵ�͵���true�����һᱻ���õ�����more��ȥ��

       ע�⣬������flags��FLAG_USE_CHILD_DRAWING_ORDERλ����0��ʱ�򣬾ͱ�ʾ��ǰ��ͼ�������ͼ��������������children�е�λ�ô�С����������ƣ�����Ļ�������Ҫͨ��ViewGroup��ij�Ա����getChildDrawingOrder��������Щ����ͼ�Ļ���˳��

       ���ǽ��������Ķ����룺

  1. // Draw any disappearing views that have animations  
  2. if (mDisappearingChildren != null) {  
  3.     final ArrayList disappearingChildren = mDisappearingChildren;  
  4.     final int disappearingCount = disappearingChildren.size() - 1;  
  5.     // Go backwards -- we may delete as animations finish  
  6.     for (int i = disappearingCount; i >= 0; i--) {  
  7.         final View child = disappearingChildren.get(i);  
  8.         more |= drawChild(canvas, child, drawingTime);  
  9.     }  
  10. }  
// Draw any disappearing views that have animations if (mDisappearingChildren != null) { final ArrayList disappearingChildren = mDisappearingChildren; final int disappearingCount = disappearingChildren.size() - 1; // Go backwards -- we may delete as animations finish for (int i = disappearingCount; i >= 0; i--) { final View child = disappearingChildren.get(i); more |= drawChild(canvas, child, drawingTime); } }       ViewGroup��ij�Ա����mDisappearingChildren����������Щ������ʧ������ͼ��������Щ����ͼ������ʾ�����Ĺ����У���ˣ���Щ����ͼҲ����Ҫ���Ƶģ���δ���ͬ����ͨ������ViewGroup��ij�Ա����drawChild���������ǡ�

      ���Ǽ��������Ķ����һ�δ��룺

  1.     if (clipToPadding) {  
  2.         canvas.restoreToCount(saveCount);  
  3.     }  
  4.   
  5.     // mGroupFlags might have been updated by drawChild()  
  6.     flags = mGroupFlags;  
  7.   
  8.     if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) {  
  9.         invalidate();  
  10.     }  
  11.   
  12.     if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 &&  
  13.             mLayoutAnimationController.isDone() && !more) {  
  14.         // We want to erase the drawing cache and notify the listener after the  
  15.         // next frame is drawn because one extra invalidate() is caused by  
  16.         // drawChild() after the animation is over  
  17.         mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER;  
  18.         final Runnable end = new Runnable() {  
  19.            public void run() {  
  20.                notifyAnimationListener();  
  21.            }  
  22.         };  
  23.         post(end);  
  24.     }  
  25. }  
  26.   
  27. ......  
if (clipToPadding) { canvas.restoreToCount(saveCount); } // mGroupFlags might have been updated by drawChild() flags = mGroupFlags; if ((flags & FLAG_INVALIDATE_REQUIRED) == FLAG_INVALIDATE_REQUIRED) { invalidate(); } if ((flags & FLAG_ANIMATION_DONE) == 0 && (flags & FLAG_NOTIFY_ANIMATION_LISTENER) == 0 && mLayoutAnimationController.isDone() && !more) { // We want to erase the drawing cache and notify the listener after the // next frame is drawn because one extra invalidate() is caused by // drawChild() after the animation is over mGroupFlags |= FLAG_NOTIFY_ANIMATION_LISTENER; final Runnable end = new Runnable() { public void run() { notifyAnimationListener(); } }; post(end); } } ...... }        ��δ���ִ����������������

        1. ������clipToPadding��ֵ�Ƿ����true������ǵĻ�����ô��˵��ǰ�����ù�����canvas��������һ�黭���IJü��������������Ѿ�����黭���ϻ�����ɵ�ǰ��ͼ���UI�ˣ���ˣ�����Ҫ�ָ�����canvas��������һ�黭����ջ״̬������ͨ�����ò���canvas��ָ���һ��Canvas����ij�Ա����restoreToCount��ʵ�ֵġ�

        2. ǰ���ڻ��Ƶ�ǰ��ͼ�������ͼ��UI��ʱ���п��ܻ���Ҫ�޸ĵ�ǰ��ͼ��ı�־λ�����޸�ViewGroup��ij�Ա����mGroupFlags��ֵ������޸ĺ��mGroupFlags��FLAG_INVALIDATE_REQUIREDλ����1����ô��˵����ǰ��ͼ����Ҫ���·���һ������UI����������ͨ������ViewGroup�������һ����Ա����invalidate��ʵ�ֵġ�

        3. �����ǰ��ͼ��Ķ����Ѿ���ʾ��ɣ����ҵ�ǰ��ͼ�������ͼ�Ķ���Ҳ�Ѿ���ʾ��ɣ��ٲ��ҵ�ǰ��ͼ��ע���ж��������ߣ���ô���ǻ����ViewGroup�������һ����Ա����notifyAnimationListener��֪ͨ��Щ���������ߣ���ǰ��ͼ��Ķ����Ѿ���ʾ������ע�⣬ViewGroup��ij�Ա����notifyAnimationListener������Ϣ����ʽ�����õģ���ViewGroup��ij�Ա����dispatchDraw�����ڶ���һ��ʾ������������֪ͨ��Щ���������ߡ�

        �����������Ǿͼ�������ViewGroup��ij�Ա����drawChild��ʵ�֣��Ա�����˽�һ����ͼ�������ͼ�Ļ��ƹ��̡�

        Step 10. ViewGroup.drawChild

        ��������������ļ�frameworks/base/core/java/android/view/ViewGroup.java�У�����ʵ�ֱȽϳ������Ƿֶ����Ķ���

  1. public abstract class ViewGroup extends View implements ViewParent, ViewManager {  
  2.     ......  
  3.   
  4.     protected boolean drawChild(Canvas canvas, View child, long drawingTime) {  
  5.         boolean more = false;  
  6.   
  7.         final int cl = child.mLeft;  
  8.         final int ct = child.mTop;  
  9.         final int cr = child.mRight;  
  10.         final int cb = child.mBottom;  
  11.   
  12.         final int flags = mGroupFlags;  
public abstract class ViewGroup extends View implements ViewParent, ViewManager { ...... protected boolean drawChild(Canvas canvas, View child, long drawingTime) { boolean more = false; final int cl = child.mLeft; final int ct = child.mTop; final int cr = child.mRight; final int cb = child.mBottom; final int flags = mGroupFlags;

       ��δ������Ȼ������ͼchild������cl, ct, cr, cb�����Լ���ǰ��ͼ��ı�־λflags���Ա����������ʹ�á����⣬����more��ֵ������ʾ����ͼchild�Ƿ�����ʾ������

       ���ǽ��������Ķ����룺

  1. Transformation transformToApply = null;  
  2. final Animation a = child.getAnimation();  
  3. ......  
  4.   
  5. if (a != null) {  
  6.     ......  
  7.   
  8.     if (mChildTransformation == null) {  
  9.         mChildTransformation = new Transformation();  
  10.     }  
  11.     more = a.getTransformation(drawingTime, mChildTransformation);  
  12.     transformToApply = mChildTransformation;  
  13.     ......  
  14.   
  15. else if ((flags & FLAG_SUPPORT_STATIC_TRANSFORMATIONS) ==  
  16.         FLAG_SUPPORT_STATIC_TRANSFORMATIONS) {  
  17.     if (mChildTransformation == null) {  
  18.         mChildTransformation = new Transformation();  
  19.     }  
  20.     final boolean hasTransform = getChildStaticTransformation(child, mChildTransformation);  
  21.     if (hasTransform) {  
  22.         final int transformType = mChildTransformation.getTransformationType();  
  23.         transformToApply = transformType != Transformation.TYPE_IDENTITY ?  
  24.                 mChildTransformation : null;  
  25.         ......  
  26.     }  
  27. }  
Transformation transformToApply = null; final Animation a = child.getAnimation(); ...... if (a != null) { ...... if (mChildTransformation == null) { mChildTransformation = new Transformation(); } more = a.getTransformation(drawingTime, mChildTransformation); transformToApply = mChildTransformation; ...... } else if ((flags & FLAG_SUPPORT_STATIC_TRANSFORMATIONS) == FLAG_SUPPORT_STATIC_TRANSFORMATIONS) { if (mChildTransformation == null) { mChildTransformation = new Transformation(); } final boolean hasTransform = getChildStaticTransformation(child, mChildTransformation); if (hasTransform) { final int transformType = mChildTransformation.getTransformationType(); transformToApply = transformType != Transformation.TYPE_IDENTITY ? mChildTransformation : null; ...... } }        ��δ��������������ͼchild�ı任����transformToApply�����������ͼchild�ı任����transformToApply֮�����ǾͿ���֪���������ʾ���ˡ� ����������£�����ͼchild�ᱻ����һ���任���󡣵�һ���������ͼchild������ʾ�����Ĺ����У��ڶ�������ǵ�ǰ��ͼ���ÿһ������ͼ������һ���任�����������Ǿͷֱ����������������

       ���ڵ�һ�����������ͼchild�ij�Ա����getAnimation�ķ���ֵa������null����������ָ���һ��Animation�������������������ͼchild�Ķ����ġ����������ͼ�Ķ�������a֮�����ǾͿ��Ե������ij�Ա����getTransformation������ִ�����Ķ����ˡ�����ö�������Ҫ����ִ�У���ô����Animation����a�ij�Ա����getTransformation�ķ���ֵmore�ͻ����true�����һ᷵������ͼchild�Ľ�������Ҫʹ�õı任���󣬱�����ViewGroup��ij�Ա����mChildTransformation�С�ViewGroup��ij�Ա����mChildTransformation����ֻᱣ���ڱ���transformToApply�С�

       ���ڵڶ������������flags��FLAG_SUPPORT_STATIC_TRANSFORMATIONSλ����1����ʱ�����ViewGroup��ij�Ա����getChildStaticTransformation�Ϳ���֪������ͼchild�Ƿ�������һ���任������������˵Ļ�����ôViewGroup��ij�Ա����getChildStaticTransformation�ķ���ֵhasTransform�ͻ����true������������£�ViewGroup��ij�Ա����mChildTransformation�������ı任�������ҪӦ��������ͼchild�еġ�������һ��ǰ�ᣬ��ViewGroup��ij�Ա����mChildTransformation�������ı任������һ����λ����������Ϊ��λ������û�б任Ч���ġ����ViewGroup��ij�Ա����mChildTransformation�������ı任������һ����λ������ô��ͬ���ᱻ�����ڱ���transformToApply�С�

 

 δ�ꡣ����

��������
��������(0)
���� *
�������� *
��֤�� *ͼƬ�����壿������µõ���֤��