View的绘制

来源:互联网 发布:网络课程评价标准 编辑:程序博客网 时间:2024/06/16 22:43



view的绘制主要有三步:onMeasure ,onLayout,,onDraw。这三步又分两种情况,view和viewgroup的测绘。viewgroup主要是对子元素的遍历再调用view的测绘过程。所以主要研究view的测绘就好。

    onMeasure源码:

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),                getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));    }

public static int getDefaultSize(int size, int measureSpec) {        int result = size;        int specMode = MeasureSpec.getMode(measureSpec);        int specSize = MeasureSpec.getSize(measureSpec);        switch (specMode) {        case MeasureSpec.UNSPECIFIED:            result = size;            break;        case MeasureSpec.AT_MOST:        case MeasureSpec.EXACTLY:            result = specSize;            break;        }        return result;    }
从上述源码可以看出view的大小最终调用setMeasuredDimension方法,而setMeasuredDimension又由getDefaultSize来决定大小。从源码可以看出对MeasureSpec.AT_MOST情况求解size,

MeasureSpec.AT_MOST与MeasureSpec.UNSPECIFIED是一样的情况,所以在自定义中需要对MeasureSpec.AT_MOST进行说明和分析。

onLayout源码:

 public void layout(int l, int t, int r, int b) {        int oldL = mLeft;        int oldT = mTop;        int oldB = mBottom;        int oldR = mRight;        boolean changed = setFrame(l, t, r, b);        if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {            onLayout(changed, l, t, r, b);            mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;            ListenerInfo li = mListenerInfo;            if (li != null && li.mOnLayoutChangeListeners != null) {                ArrayList<OnLayoutChangeListener> listenersCopy =                        (ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();                int numListeners = listenersCopy.size();                for (int i = 0; i < numListeners; ++i) {                    listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);                }            }        }        mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;    }
整个过程很简单就是确定view四个顶点的位置。这样view的位置也就确定了。

onDraw源码:

 public void draw(Canvas canvas) {        final int privateFlags = mPrivateFlags;        final boolean dirtyOpaque = (privateFlags & PFLAG_DIRTY_MASK) == PFLAG_DIRTY_OPAQUE &&                (mAttachInfo == null || !mAttachInfo.mIgnoreDirtyState);        mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_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 = 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            dispatchDraw(canvas);            // Step 6, draw decorations (scrollbars)            onDrawScrollBars(canvas);            // we're done...            return;        }
总结draw的过程是:1,.绘制背景。2,绘制自己。3,绘制chilidren,4,绘制修饰。

      

0 0