你用对了吗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() 调用(如批量更新属性)。
相关推荐
每次的天空32 分钟前
Android-自定义View的实战学习总结
android·学习·kotlin·音视频
恋猫de小郭1 小时前
Flutter Widget Preview 功能已合并到 master,提前在体验毛坯的预览支持
android·flutter·ios
断剑重铸之日2 小时前
Android自定义相机开发(类似OCR扫描相机)
android
随心最为安2 小时前
Android Library Maven 发布完整流程指南
android
岁月玲珑2 小时前
【使用Android Studio调试手机app时候手机老掉线问题】
android·ide·android studio
还鮟6 小时前
CTF Web的数组巧用
android
小蜜蜂嗡嗡8 小时前
Android Studio flutter项目运行、打包时间太长
android·flutter·android studio
aqi008 小时前
FFmpeg开发笔记(七十一)使用国产的QPlayer2实现双播放器观看视频
android·ffmpeg·音视频·流媒体
zhangphil9 小时前
Android理解onTrimMemory中ComponentCallbacks2的内存警戒水位线值
android
你过来啊你9 小时前
Android View的绘制原理详解
android