View的draw onDraw dispatchDraw顺序

本文详细介绍了Android中View组件的绘制流程,包括如何通过onDraw()和dispatchDraw()方法来绘制视图及其子组件。此外还探讨了背景Drawable的影响及如何通过自定义Drawable来控制视图的大小。

绘制VIew本身的内容,通过调用View.onDraw(canvas)函数实现

绘制自己的孩子通过dispatchDraw(canvas)实现

 

    View组件的绘制会调用draw(Canvas canvas)方法,draw过程中主要是先画Drawable背景,对 drawable调用setBounds()然后是draw(Canvas c)方法.有点注意的是背景drawable的实际大小会影响view组件的大小,drawable的实际大小通过getIntrinsicWidth()和getIntrinsicHeight()获取,当背景比较大时view组件大小等于背景drawable的大小

     画完背景后,draw过程会调用onDraw(Canvas canvas)方法,然后就是dispatchDraw(Canvas canvas)方法, dispatchDraw()主要是分发给子组件进行绘制,我们通常定制组件的时候重写的是onDraw()方法。值得注意的是ViewGroup容器组件的绘制,当它没有背景时直接调用的是dispatchDraw()方法, 而绕过了draw()方法,当它有背景的时候就调用draw()方法,而draw()方法里包含了dispatchDraw()方法的调用。因此要在ViewGroup上绘制东西的时候往往重写的是dispatchDraw()方法而不是onDraw()方法,或者自定制一个Drawable,重写它的draw(Canvas c)和 getIntrinsicWidth(), 

getIntrinsicHeight()方法,然后设为背景。

参见http://blog.youkuaiyun.com/czh0766/archive/2010/08/05/5790295.aspx

### Android 视图绘制流程中的 `onDraw` 方法执行顺序 在 Android 的视图绘制流程中,`onDraw` 方法是绘制视图内容的核心部分。以下是关于 `onDraw` 方法在绘制时的执行顺序和调用流程的详细说明: #### 1. 绘制流程概述 Android 的视图绘制过程可以分为三个主要阶段:**Measure**、**Layout** 和 **Draw**。`onDraw` 方法属于 Draw 阶段的一部分[^1]。 #### 2. `onDraw` 的调用时机 `onDraw` 方法会在 `View.draw()` 方法中被调用。具体来说,当一个视图需要重新绘制时,系统会通过 `invalidate()` 或 `postInvalidate()` 方法触发重新绘制流程。这个流程最终会调用到 `ViewRootImpl.performDraw()` 方法[^2]。 #### 3. `onDraw` 的执行顺序 在 `View.draw()` 方法中,`onDraw` 的执行顺序如下: 1. **绘制背景** 首先会调用 `drawBackground(canvas)` 方法绘制视图的背景。 2. **调用 `onDraw` 方法** 如果没有设置边框绘制(即 `verticalEdges` 和 `horizontalEdges` 均为 `false`),则会调用 `onDraw(canvas)` 方法。这是开发者自定义绘制逻辑的地方。 3. **子视图绘制** 对于 `ViewGroup` 类型的视图,还会调用 `dispatchDraw(canvas)` 方法绘制其子视图。 #### 4. 具体代码路径 以下是 `onDraw` 方法在绘制流程中的调用路径: ```java // ViewRootImpl.java private void performDraw() { try { draw(fullRedrawNeeded); } finally { // 清理资源 } } private boolean draw(boolean fullRedrawNeeded) { if (!drawSoftware(surface, mAttachInfo, xOffset, yOffset, scalingRequired, dirty, surfaceInsets)) { return false; } if (animating) { scheduleTraversals(); // 如果有动画,则重新调度绘制任务 } return true; } private boolean drawSoftware(Surface surface, AttachInfo attachInfo, int xoff, int yoff, boolean scalingRequired, Rect dirty, Rect surfaceInsets) { mView.draw(canvas); // 调用视图的 draw 方法 } // View.java public void draw(Canvas canvas) { // 绘制背景 drawBackground(canvas); if (!verticalEdges && !horizontalEdges) { // 调用 onDraw 方法 onDraw(canvas); } // 如果是 ViewGroup,则绘制子视图 dispatchDraw(canvas); } ``` #### 5. 注意事项 - **覆盖 `onDraw` 方法** 开发者可以通过重写 `onDraw` 方法来自定义视图的绘制逻辑。例如,绘制文本、图形或图像等。 - **性能优化** 在 `onDraw` 方法中尽量减少复杂计算和频繁的内存分配操作,以避免影响绘制性能。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值