你用对了吗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() 调用(如批量更新属性)。
相关推荐
八月林城5 分钟前
echarts在uniapp中使用安卓真机运行时无法显示的问题
android·uni-app·echarts
雨白20 分钟前
搞懂 Fragment 的生命周期
android
casual_clover23 分钟前
Android 之 kotlin语言学习笔记三(Kotlin-Java 互操作)
android·java·kotlin
梓仁沐白29 分钟前
【Kotlin】数字&字符串&数组&集合
android·开发语言·kotlin
技术小甜甜35 分钟前
【Godot】如何导出 Release 版本的安卓项目
android·游戏引擎·godot
火柴就是我1 小时前
Dart 原始字符串(Raw Strings)详解文档
android
玲小珑1 小时前
Auto.js 入门指南(五)实战项目——自动脚本
android·前端
玲小珑1 小时前
Auto.js 入门指南(四)Auto.js 基础概念
android·前端
没有了遇见2 小时前
DrawerLayout 滑动冲突
android
玲小珑3 小时前
Auto.js 入门指南(六)多线程与异步操作
android·前端