你用对了吗Requestlayout,onlayout,onDraw,DrawChild

在 Android 的视图系统中,requestLayout()onLayout()onDraw()drawChild() 是视图布局(Layout)和绘制(Draw)流程中的关键方法。它们的作用和调用顺序密切相关,但职责不同。以下是它们的区别和联系:


1. requestLayout()

  • 作用
    请求对视图树进行重新测量(measure)和布局(layout)。当 View 的尺寸或位置发生变化(例如内容改变、子 View 动态添加/移除)时,需要调用此方法触发重新布局。
  • 触发流程
    调用 requestLayout() 后,系统会从当前 View 向上回溯到根 View(ViewRootImpl),触发整个视图树的 measure()layout() 流程,最终可能导致 onLayout() 被调用。
  • 注意
    • 不会直接触发 onDraw()(重绘需要 invalidate())。
    • 频繁调用可能导致性能问题(如布局抖动)。

2. onLayout()

  • 作用
    确定 View 及其子 View 的位置和尺寸。在布局流程中,父 View(通常是 ViewGroup)通过 onLayout() 安排子 View 的位置。
  • 触发时机
    measure() 流程完成后,由 layout() 方法调用。
  • 关键行为
    • ViewGroup:遍历子 View,调用每个子 View 的 layout(l, t, r, b) 方法,设置其位置。
    • 对普通 View:默认无操作(因为单个 View 的位置由父 View 直接设置)。

3. onDraw()

  • 作用
    绘制 View 的视觉内容(如背景、文字、自定义图形)。通过 Canvas 对象实现具体绘制逻辑。
  • 触发时机
    在绘制流程中,由 View.draw() 方法调用。调用 invalidate() 或界面需要更新(如首次显示、动画)时会触发重绘。
  • 注意
    • 不要在此方法中创建对象或执行耗时操作(可能引发卡顿)。
    • 若需要强制重绘,调用 invalidate()postInvalidate()(非 UI 线程)。

4. drawChild()

  • 作用
    ViewGroup 的方法,用于绘制子 View。在 ViewGroup 的绘制流程中,会遍历子 View 并调用 drawChild(),最终触发子 View 的 draw() 方法。
  • 触发时机
    ViewGroupdispatchDraw() 方法中被调用(dispatchDraw()View.draw() 的一部分)。
  • 关键行为
    • 处理子 View 的绘制顺序、裁剪区域、动画等。
    • 默认实现直接调用子 View 的 draw() 方法,但可重写以实现特殊效果(如叠加绘制内容)。

联系与流程

  1. 布局流程
    requestLayout() → 触发 measure()onMeasure()layout()onLayout()

    • 当 View 的尺寸或位置需要更新时调用 requestLayout(),最终触发 onLayout() 重新排列子 View。
  2. 绘制流程
    invalidate() → 触发 draw()onDraw()dispatchDraw()drawChild()

    • onDraw() 负责绘制自身内容,drawChild() 负责绘制子 View。
  3. 协作关系

    • requestLayout() 影响布局,可能导致重绘(因位置变化)。
    • onLayout() 确定子 View 的位置,drawChild() 确保子 View 被正确绘制。
    • onDraw()drawChild() 属于同一绘制流程,但作用对象不同(自身 vs 子 View)。

总结对比

方法 归属 作用 触发条件
requestLayout() View 触发重新测量和布局 View 尺寸/结构变化
onLayout() View/ViewGroup 安排子 View 的位置 布局流程(layout() 调用)
onDraw() View 绘制自身内容 绘制流程(draw() 调用)
drawChild() ViewGroup 绘制单个子 View dispatchDraw() 遍历子 View

使用场景

  • 自定义 View

    • 重写 onLayout():调整子 View 的位置(如实现流式布局)。
    • 重写 onDraw():实现自定义绘制(如圆形进度条)。
    • 重写 drawChild():在子 View 绘制时添加额外效果(如统一阴影)。
  • 性能优化

    • 避免在 onDraw() 中频繁创建对象(如 Paint)。
    • 减少不必要的 requestLayout() 调用(如批量更新属性)。
相关推荐
ai2work2 小时前
ch15 加载模型与初始化上下文
kotlin
hai_android3 小时前
Kotlin / Android 常用函数使用示例手册
android·java·kotlin
hai_android4 小时前
Android MeasureSpec 详解
android·java·kotlin
又见情义6 小时前
RK3568 Android 13 本地 U 盘 OTA 升级实战:基于 RKUpdateService 的完整流程
android
Godikov7 小时前
Android10后台弹窗与APK自动更新
android
ai2work7 小时前
ch11 持久化:DataStore + Gson 多会话
kotlin
又见情义8 小时前
RK3568 Android 13 USB OTG/Host 切换调试经验分享
android
终端安全笔记9 小时前
iOS 27 之后「策略空转」:设备升级不报错,但旧策略不再管它
android·网络·安全·ios·智能手机
JMchen10 小时前
实战案例:实现120fps流畅的渐变进度条
android·kotlin·canvas
敲代码的瓦龙10 小时前
Jetpack?DataBinding!!!
android·java·开发语言·mysql·android-studio