你用对了吗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() 调用(如批量更新属性)。
相关推荐
火柴就是我35 分钟前
android:enableJetifier=true 再学习
android·flutter
杨筱毅36 分钟前
【Android】【底层原理】深入解析SELinux模块
android·底层机制
Tom4i1 小时前
基于 Launcher3 的 iOS 风格桌面 04 拖拽和移位
android
2501_915106321 小时前
iOS 反编译防护工具与实战组合 从静态侦察到 IPA 成品加固的工程化路径
android·ios·小程序·https·uni-app·iphone·webview
游戏开发爱好者84 小时前
iOS 26 iPhone 使用记录分析 多工具组合构建全方位设备行为洞察体系
android·ios·小程序·uni-app·cocoa·iphone·webview
zhangphil11 小时前
HARDWARE 属性的Bitmap与普通Bitmap,GPU与RenderThread渲染与处理方式异同比较,Android
android
消失的旧时光-194313 小时前
Flutter 异步编程:Future 与 Stream 深度解析
android·前端·flutter
alexhilton14 小时前
Compose CameraX现已稳定:给Composer的端到端指南
android·kotlin·android jetpack
阿里云云原生16 小时前
移动端性能监控探索:可观测 Android 采集探针架构与实现
android
雨白16 小时前
玩转 Flow 操作符(一):数据转换与过滤
android·kotlin