在 Android 中,自定义 View 的绘制流程

ops/2024/9/23 5:17:05/

目录

1. 测量阶段 (onMeasure())

2. 布局阶段 (onLayout())

3. 绘制阶段 (onDraw())

总体绘制流程

注意事项

示例总结

参考资料


在 Android 中,自定义 View 的绘制流程主要包括测量布局绘制三个关键步骤。具体来说,自定义 View 的绘制涉及重写系统的 onMeasure()onLayout()onDraw() 方法。下面详细介绍这个流程:

1. 测量阶段 (onMeasure())

onMeasure() 方法用于确定 View 的尺寸。系统会调用该方法来让自定义 View 计算其宽度和高度。你可以根据父布局给定的测量模式和尺寸对 View 进行自适应处理。

  • 系统提供了三种测量模式:
    1. EXACTLY: 父布局强制给定的大小。自定义 View 必须使用该大小。
    2. AT_MOST: 父布局允许的最大尺寸。View 可以小于或等于这个尺寸。
    3. UNSPECIFIED: 父布局对 View 的尺寸没有任何限制。

示例:

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int widthMode = MeasureSpec.getMode(widthMeasureSpec);int heightMode = MeasureSpec.getMode(heightMeasureSpec);int widthSize = MeasureSpec.getSize(widthMeasureSpec);int heightSize = MeasureSpec.getSize(heightMeasureSpec);// 计算出自定义 View 的大小int width = calculateWidth(widthMode, widthSize);int height = calculateHeight(heightMode, heightSize);// 调用 setMeasuredDimension 设置测量的宽高setMeasuredDimension(width, height);
}

2. 布局阶段 (onLayout())

onLayout() 方法用于安排子 View 的位置。自定义 View 本身没有子 View 时,通常不需要重写此方法。只有自定义 ViewGroup(包含子 View 的容器)时才需要重写。

onLayout() 中,确定每个子 View 的摆放位置,可以通过 child.layout(left, top, right, bottom) 来安排子 View 的布局。

示例:

@Override
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {// 如果有子 View,调用每个子 View 的 layout() 方法设置它们的位置int childCount = getChildCount();for (int i = 0; i < childCount; i++) {View child = getChildAt(i);child.layout(left, top, right, bottom); // 设置子 View 的位置}
}

3. 绘制阶段 (onDraw())

onDraw() 方法用于执行实际的绘制操作。开发者可以通过重写该方法来定义自定义 View 的外观。在 onDraw() 中,使用 Canvas 对象绘制图形、文本、图片等。

onDraw() 方法中:

  • 使用 Canvas 提供的方法来绘制图形(如 drawRect()drawCircle() 等)。
  • Paint 对象用于设置绘制样式,如颜色、线条粗细、字体等。

示例:

@Override
protected void onDraw(Canvas canvas) {super.onDraw(canvas);// 设置画笔Paint paint = new Paint();paint.setColor(Color.BLUE);paint.setStyle(Paint.Style.FILL);// 画一个圆canvas.drawCircle(getWidth() / 2, getHeight() / 2, Math.min(getWidth(), getHeight()) / 2, paint);
}

总体绘制流程

  1. Measure: 首先调用 onMeasure() 方法,测量 View 的尺寸并传递给 View 的父布局。父布局基于测量结果决定如何分配空间给子 View。

  2. Layout: 在测量结束后,调用 onLayout() 方法对 View 进行布局。对于自定义 ViewGroup,父布局会传递给子 View 的具体位置坐标。

  3. Draw: 布局完成后,系统会调用 onDraw() 方法。onDraw() 主要负责绘制内容,例如图形、文字等。绘制顺序为:

  • 背景
  • 自身内容(如文字、图形)
  • 子 View
  • 滑动条等装饰

注意事项

  • 在执行 onDraw() 时,确保绘制效率。如果绘制操作过于复杂,可能会导致卡顿,应尽量避免在 onDraw() 中进行复杂的计算。
  • 重写 onMeasure() 时,必须调用 setMeasuredDimension() 来设置 View 的宽高,否则系统将无法正确布局该 View。
  • 需要使用 invalidate() 来触发重新绘制操作。

示例总结

public class CustomView extends View {public CustomView(Context context) {super(context);}public CustomView(Context context, AttributeSet attrs) {super(context, attrs);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int width = MeasureSpec.getSize(widthMeasureSpec);int height = MeasureSpec.getSize(heightMeasureSpec);setMeasuredDimension(width, height);}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);Paint paint = new Paint();paint.setColor(Color.RED);paint.setStyle(Paint.Style.FILL);canvas.drawCircle(getWidth() / 2, getHeight() / 2, 100, paint);}
}

参考资料

  • Android Developers: Custom Views

http://www.ppmy.cn/ops/113562.html

相关文章

C++析构函数为什么要为虚函数?

目录 1.引言 2.原因 3.示例分析 4.总结 1.引言 在C中&#xff0c;将析构函数声明为虚函数&#xff08;virtual destructor&#xff09;的主要原因是为了支持多态删除&#xff08;polymorphism with deletion&#xff09;。多态允许通过基类指针或引用来操作派生类对象&…

LabVIEW机械产品几何精度质检系统

随着制造业的发展&#xff0c;对产品质量的要求越来越高&#xff0c;机械产品的几何精度成为衡量其品质的重要指标。为了提高检测效率和精度&#xff0c;开发了一套基于LabVIEW的几何精度质检系统&#xff0c;该系统不仅可以自动化地进行几何尺寸的测量&#xff0c;而且能实时分…

【Kubernetes】常见面试题汇总(二十一)

目录 65.简述 Kubernetes 中&#xff0c;如何使用 EFK 实现日志的统一管理&#xff1f; 66.简述 Kubernetes 如何进行优雅的节点关机维护&#xff1f; 67.简述 Kubernetes 集群联邦&#xff1f; 65.简述 Kubernetes 中&#xff0c;如何使用 EFK 实现日志的统一管理&#xff1…

自动登录 RPA 的进阶:滑块验证的巧妙实现

​在RPA的众多应用场景的探索中&#xff0c;自动登录是一个至关重要的环节&#xff0c;它为后续的自动化操作奠定了基础。然而&#xff0c;当我们面对滑块验证这一常见的挑战时&#xff0c;常常会感到困惑和无从下手。本文就来分享自动登录RPA的进阶----滑块验证如何实现。 在…

网站SEO,该如何规范目标网站URL配置!

随着互联网技术的飞速发展&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;在网站建设和运营中的重要性日益凸显。优化目标网站的URL配置&#xff0c;作为SEO策略中的关键环节&#xff0c;对于提升网站在搜索引擎中的排名和曝光度具有至关重要的作用。大连蝙蝠侠科技将从U…

[ IDE ] SEGGER Embedded Studio for RISC-V

一、FILE 二、Edit 三、View 四、Search 五、Navigate 六、Project 七、Build 7.1 编译 先选择一个目标类型&#xff0c;再选择编译。 八、Debug 九、Target 十、Tools 10.1 自定义快捷键 点击菜单项&#xff0c;通过Tools –> Options –> Keyboard&#xff0c;实现自…

【自动化测试】UI自动化的分类、如何选择合适的自动化测试工具以及其中appium的设计理念、引擎和引擎如何工作

引言 UI自动化测试主要针对软件的用户界面进行测试&#xff0c;以确保用户界面元素的交互和功能符合预期 文章目录 引言一、UI自动化的分类1.1 基于代码的自动化测试1.2 基于录制/回放的自动化测试1.3 基于框架的自动化测试1.4 按测试对象分类1.5 按测试层次分类1.6 按测试执行…

ARM驱动学习之21_字符驱动

ARM驱动学习之21_字符驱动 操作步骤&#xff1a; file_operations中的函数比较多&#xff0c; 选取用的比较多的函数简单介绍&#xff0c; 后 面的驱动教程中调用了对应的函数• int (*open) (struct inode *, struct file *) – 打开函数 • int (*release) (struct inode *…