Android View繪制流程 - 當空皓月的個人空間

jopen 8年前發布 | 7K 次閱讀 Android開發 移動開發

剛開始時,當想要自己繪制一些自定義組件的時候,會覆蓋onDraw方法,然后,在里面利用canvas繪制一些自己想要的圖形,而最近遇到一個問題,就是onDraw函數不起作用了。然后,搜了半天資料,才知道onDraw并不是萬能的。

首先,大概介紹一下Android draw的大概流程,下面截取的是Android關于View中draw方法的一部分:

public void draw(Canvas canvas) { 
   final boolean dirtyOpaque = (privateFlags & DIRTY_MASK) == DIRTY_OPAQUE && 
           (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState); 
   mPrivateFlags = (privateFlags & ~DIRTY_MASK) | DRAWN; 

   /* 
    * Draw traversal performs several drawing steps which must be executed 
    * in the appropriate order: 
    * 
    *      1. Draw the background 
    *      2. If necessary, save the canvas' layers to prepare for fading 
    *      3. Draw view's content 
    *      4. Draw children 
    *      5. If necessary, draw the fading edges and restore layers 
    *      6. Draw decorations (scrollbars for instance) 
    */ 

   // Step 1, draw the background, if needed 
   int saveCount; 

   if (!dirtyOpaque) { 
       final Drawable background = mBGDrawable; 
       if (background != null ) { 
           ... ... // draw background 
       } 
   } 

   // 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 ; 
   } 
   ... 
} 


可以看到,View先是繪制background,然后是自己的content,然后是dispatchDraw。繪制自己的content自然是去調用onDraw,而判斷的依據就是dirtyOpaque。而在View的構造方法中,會調用一個方法:computeOpaqueFlags,這個方法的說明如下:

protected void computeOpaqueFlags() { 
   // Opaque if: 
   //   - Has a background 
   //   - Background is opaque 
   //   - Doesn't have scrollbars or scrollbars are inside overlay 
  ... ... 

可以看出, 判斷一個View是否為Opaque的幾個條件。顯然,對于ViewGroup(如LinearLayout…),他們是沒有background的,自然,當執行draw方法的時候,不會觸發自己的onDraw。

那么,為什么要這么做呢?這主要是考慮的性能優化,因為ViewGroup一般是用來當做容器用的,不需要承擔顯示的任務,所以,我們自己最好也不要這樣做。如果非得想要調用自己的onDraw方法,有兩個辦法:一是給ViewGroup設置一個背景色,另一個辦法就是設置setWillNotDraw為false。

實際中,我們如果想自己實現一個定制化的UI,當面對的是ViewGroup的時候,首先想到的是覆蓋dispatchDraw這個方法。

原文地址:http://lishoubo.github.io/2012/08/14/android-ondraw-and-dispatchdraw/ 

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!