android view draw,Android系统_View.draw解析

图文概括

流程

绘制背景

绘制内容

分发子View绘制

绘制装饰

9b759b4a1aa5

源码分析

View.draw

public void draw(Canvas canvas) {

....

// 1. 绘制本身View背景

if (!dirtyOpaque) {

drawBackground(canvas);

}

if (!verticalEdges && !horizontalEdges) {

// Step 3, draw the content

// 2. 绘制内容,默认空实现 需复写

if (!dirtyOpaque) onDraw(canvas);

// 3. 绘制 children

dispatchDraw(canvas);

drawAutofilledHighlight(canvas);

// 4. 分发Draw (单一View空实现,ViewGroup见下面分析)

if (mOverlay != null && !mOverlay.isEmpty()) {

mOverlay.getOverlayView().dispatchDraw(canvas);

}

// 5. 绘制装饰 (前景色,滚动条)

onDrawForeground(canvas);

return;

}

....

}

//绘制背景

private void drawBackground(Canvas canvas) {

final Drawable background = mBackground;

if (background == null) {

return;

}

// 根据在 layout 过程中获取的 View 的位置参数,来设置背景的边界

setBackgroundBounds();

// 先尝试用HWUI绘制

if (canvas.isHardwareAccelerated() && mAttachInfo != null

&& mAttachInfo.mThreadedRenderer != null) {

mBackgroundRenderNode = getDrawableRenderNode(background, mBackgroundRenderNode);

final RenderNode renderNode = mBackgroundRenderNode;

if (renderNode != null && renderNode.isValid()) {

setBackgroundRenderNodeProperties(renderNode);

((DisplayListCanvas) canvas).drawRenderNode(renderNode);

return;

}

}

final int scrollX = mScrollX;

final int scrollY = mScrollY;

if ((scrollX | scrollY) == 0) {

//调用 Drawable 的 draw 方法来进行背景的绘制

background.draw(canvas);

} else {

// 若 mScrollX 和 mScrollY 有值,则对 canvas 的坐标进行偏移平移画布

canvas.translate(scrollX, scrollY);

//调用 Drawable 的 draw 方法来进行背景的绘制

background.draw(canvas);

canvas.translate(-scrollX, -scrollY);

}

}

// 绘制View本身内容,空实现,子类必须复写

protected void onDraw(Canvas canvas) {

}

// 单一View无子View,空实现

protected void dispatchDraw(Canvas canvas) {

}

public void onDrawForeground(Canvas canvas) {

//绘制指示器

onDrawScrollIndicators(canvas);

//绘制滚动条

onDrawScrollBars(canvas);

final Drawable foreground = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;

if (foreground != null) {

if (mForegroundInfo.mBoundsChanged) {

mForegroundInfo.mBoundsChanged = false;

final Rect selfBounds = mForegroundInfo.mSelfBounds;

final Rect overlayBounds = mForegroundInfo.mOverlayBounds;

if (mForegroundInfo.mInsidePadding) {

selfBounds.set(0, 0, getWidth(), getHeight());

} else {

selfBounds.set(getPaddingLeft(), getPaddingTop(),

getWidth() - getPaddingRight(), getHeight() - getPaddingBottom());

}

final int ld = getLayoutDirection();

Gravity.apply(mForegroundInfo.mGravity, foreground.getIntrinsicWidth(),

foreground.getIntrinsicHeight(), selfBounds, overlayBounds, ld);

foreground.setBounds(overlayBounds);

}

//调用 Drawable 的 draw 方法,绘制前景色

foreground.draw(canvas);

}

}

ViewGroup.draw

public void draw(Canvas canvas) {

// 调用View.draw 方法

}

@Override

protected void dispatchDraw(Canvas canvas) {

...

// 1. 遍历子View

final int childrenCount = mChildrenCount;

...

for (int i = 0; i < childrenCount; i++) {

while (transientIndex >= 0 && mTransientIndices.get(transientIndex) == i) {

final View transientChild = mTransientViews.get(transientIndex);

if ((transientChild.mViewFlags & VISIBILITY_MASK) == VISIBLE ||

transientChild.getAnimation() != null) {

more |= drawChild(canvas, transientChild, drawingTime);

}

transientIndex++;

if (transientIndex >= transientCount) {

transientIndex = -1;

}

}

final int childIndex = getAndVerifyPreorderedIndex(childrenCount, i, customOrder);

final View child = getAndVerifyPreorderedView(preorderedList, children, childIndex);

if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE || child.getAnimation() != null) {

// 调用 drawChild 方法,进行子元素绘制

more |= drawChild(canvas, child, drawingTime);

}

}

....

}

-

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值