你用对了吗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() 调用(如批量更新属性)。
相关推荐
一笑的小酒馆8 小时前
Android12去掉剪贴板复制成功的Toast
android
一笑的小酒馆8 小时前
Android12App启动图标自适应
android
程序员江同学9 小时前
Kotlin 技术月报 | 2025 年 7 月
android·kotlin
某空m11 小时前
【Android】内容提供器
android
Greenland_1211 小时前
Android 编译报错 Null extracted folder for artifact: xxx activity:1.8.0
android
_frank22212 小时前
kotlin使用mybatis plus lambdaQuery报错
开发语言·kotlin·mybatis
Bryce李小白12 小时前
Kotlin实现Retrofit风格的网络请求封装
网络·kotlin·retrofit
ZhuYuxi33312 小时前
【Kotlin】const 修饰的编译期常量
android·开发语言·kotlin
jzlhll12312 小时前
kotlin StateFlow的两个问题和使用场景探讨
kotlin·stateflow
Bryce李小白12 小时前
Kotlin 实现 MVVM 架构设计总结
android·开发语言·kotlin