View繪製之draw過程

這篇博客主要爲大家介紹View繪製過程的最後一步,draw的過程。下面一張流程圖爲大家展示一下:

這裏寫圖片描述

下面這段是draw()方法的源代碼:


 /**   
     * 手動的給View(和所有它的子View)制定的Canvas.在這個方法被調用之前這個View必須已經
     * 做了一個完整的佈局。當重新繪製一個View,重載onDraw()方法代替重載這個方法。如果你要
     * 重載這個方法,先調用父View的這個方法
     * 
     * Manually render this view (and all of its children) to the given Canvas.
     * The view must have already done a full layout before this function is
     * called.  When implementing a view, implement
     * {@link #onDraw(android.graphics.Canvas)} instead of overriding this method.
     * If you do need to override this method, call the superclass version.
     *
     * @param canvas The Canvas to which the View is rendered.
     */
    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;

        /*
         * Draw必須在合適的順序下遍歷執行下面的幾個drawing步驟
         * 
         * Draw traversal performs several drawing steps which must be executed
         * in the appropriate order:
         *      
         *      //繪製背景
         *      1. Draw the background
         *      
         *      //如果有必要,爲fading去保存這個canvas的圖層
         *      2. If necessary, save the canvas' layers to prepare for fading
         *      
         *      //繪製View的內容
         *      3. Draw view's content
         *      
         *      //繪製子View
         *      4. Draw children
         *     
         *      //如果有必要,繪製fading邊框和恢復圖層
         *      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 = mBackground;
            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);
                }
            }

  // 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
            //繪製子View
            dispatchDraw(canvas);

            // Step 6, draw decorations (scrollbars)
            //繪製滾動條
            onDrawScrollBars(canvas);

            // we're done...
            return;
        }

總結:

1、View的第一步是繪製背景

/**   
     * 繪製它(背景)的邊界包括一些其他的選擇,如透明度,顏色過濾  
     * Draw in its bounds (set via setBounds) respecting optional effects such
     * as alpha (set via setAlpha) and color filter (set via setColorFilter).
     *
     * @param canvas The canvas to draw into
     */
      public abstract void draw(Canvas canvas);

2、繪製View本身的內容,調用的方法爲onDraw(canvas)方法

/**
     * 當你繪製自己的時候的實現這個方法
     * Implement this to do your drawing.
     * 
     * 用畫不覆蓋在你已經繪製了背景的畫布上
     * @param canvas the canvas on which the background will be drawn
     */
    protected void onDraw(Canvas canvas) {
    }

3、繪製子View的內容,dispatchDraw(canvas)

/**
     * 當年繪製子View的時候這個方法會被回調,這個方法通過派生類去獲得控制,在子View繪製(完成)
     * 之前,自己(View)繪製完成之後。
     * 
     * Called by draw to draw the child views. This may be overridden
     * by derived classes to gain control just before its children are drawn
     * (but after its own view has been drawn).
     * @param canvas the canvas on which to draw the view
     */
    protected void dispatchDraw(Canvas canvas) {

    }

4、繪製橫或豎的滾動條 ,調用onDrawScrollBars(canvas)方法實現

到這裏View的整個繪製過程已經分析完畢,下一篇博客將爲大家講述繪製過程可以使用的Canvas,Paint類

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章