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

目录

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.rhkb.cn/news/428172.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每天五分钟计算机视觉:将人脸识别问题转换为二分类问题

本文重点 在前面的课程中,我们学习了两种人脸识别的网络模型,这两种人脸识别网络不能算是基于距离或者Triplet loss等等完成的神经网络参数的学习。我们比较熟悉的是分类任务,那么人脸识别是否可以转变为分类任务呢? 本节课程我们将介绍一种全新的方法来学习神经网络的参…

用友U8二次开发工具KK-FULL-*****-EFWeb使用方法

1、安装: 下一步&#xff0c;下一步即可。弹出黑框不要关闭&#xff0c;让其自动执行并关闭。 2、服务配置&#xff1a; 输入服务器IP地址&#xff0c;选择U8数据源&#xff0c;输入U8用户名及账号&#xff0c;U8登录日期勾选系统日期。测试参数有效性&#xff0c;提示测试通过…

利用 FastAPI 和 Jinja2 模板引擎快速构建 Web 应用

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;它基于标准 Python 类型提示。FastAPI 支持异步编程&#xff0c;使得开发高性能的 Web 应用变得简单快捷。在本文中&#xff0c;我们将探讨如何使用 FastAPI 结合 Jinj…

VS code 查看 ${workspaceFolder} 目录指代路径

VS code 查看 ${workspaceFolder} 目录指代路径 引言正文 引言 在 VS code 创建与运行 task.json 文件 一文中我们已经介绍了如何创建属于自己的 .json 文件。在 VS code 中&#xff0c;有时候我们需要添加一些文件路径供我们导入自定义包使用&#xff0c;此时&#xff0c;我们…

OpenCV系列教程二:基本图像增强(数值运算)、滤波器(去噪、边缘检测)

文章目录 一、基本图像增强&#xff08;数值运算&#xff09;1.1 加法 &#xff08;cv2.add&#xff09;1.1.1 图像与标量相加&#xff08;调节亮度&#xff09;1.1.2 图像与图像相加&#xff08;两个图像shape要相同&#xff09;1.1.3 图像的加权加法&#xff08;渐变切换&…

基于SpringBoot+Vue+MySQL的网上租赁系统

系统展示 用户前台界面 管理员后台界面 系统背景 在当前共享经济蓬勃发展的背景下&#xff0c;网上租赁系统作为连接租赁双方的重要平台&#xff0c;正逐步改变着人们的消费观念和生活方式。通过构建一个基于SpringBoot、Vue.js与MySQL的网上租赁系统&#xff0c;我们旨在为用户…

python线程(python threading模块、python多线程)(守护线程与非守护线程)

文章目录 Python多线程入门1. Python多线程概述2. threading模块基础- Thread 类: 这是一个代表线程的类。可以通过创建Thread类的实例来新建一个线程。- Lock 类: 在多线程环境中&#xff0c;为了防止数据错乱&#xff0c;通常需要用到锁机制。Lock类提供了基本的锁功能&#…

本地搭建我的世界服务器(JAVA)简单记录

网上参考教程挺多的&#xff0c;踩了不少坑&#xff0c;简单记录一下&#xff0c;我做的是一个私人服务器&#xff0c;就是和朋友3、4个人玩。 笨蛋 MC 开服教程 先放一个比较系统和完整的教程&#xff0c;萌新可用&#xff0c;这个教程很详细&#xff0c;我只是记录一下自己的…

【C++】list容器的基本使用

一、list是什么 list的底层结构是带头双向循环链表。 相较于 vector 的连续线性空间&#xff0c;list 就显得复杂很多&#xff0c;它是由一个个结点构成&#xff0c;每个结点申请的空间并不是连续的&#xff0c;它的好处是每次插入或删除一个数据&#xff0c;就配置或释放一个…

禁忌搜索算法(TS算法)求解实例---旅行商问题 (TSP)

目录 一、采用TS求解 TSP二、 旅行商问题2.1 实际例子&#xff1a;求解 6 个城市的 TSP2.2 **求解该问题的代码**2.3 代码运行过程截屏2.4 代码运行结果截屏&#xff08;后续和其他算法进行对比&#xff09; 三、 如何修改代码&#xff1f;3.1 减少城市坐标&#xff0c;如下&am…

游戏如何对抗定制挂

近年来&#xff0c;游戏安全对抗强度相比以往更加激烈&#xff0c;具体表现在“定制挂”趋势显著。在近期收集的近万款外挂样本中&#xff0c;定制挂约占比78%&#xff0c;常见的内存修改器、变速器等通用作弊手段占比正在下降。 所谓定制挂&#xff0c;是指针对某款游戏单独开…

初写MySQL四张表:(2/4)

今天&#xff0c;我们来写第二张表。因着这四张表以及后续有相应的拓展&#xff0c;这四张环环相扣&#xff0c;所以还未写出第一张表的同学&#xff0c;可以看完第一张表&#xff0c;再来此处&#xff1a; 初写MySQL四张表:(1/4)-CSDN博客 好&#xff0c;今日表格有三张&…

easy-es动态索引支持

背景 很多项目目前都引入了es&#xff0c;由于es弥补了mysql存储及搜索查询的局限性&#xff0c;随着技术的不断迭代&#xff0c;原生的es客户端使用比较繁琐不直观&#xff0c;上手代价有点大&#xff0c;所以easy-es框架就面世了&#xff0c;学习成本很低&#xff0c;有空大…

记忆化搜索专题——算法简介力扣实战应用

目录 1、记忆化搜索算法简介 1.1 什么是记忆化搜索 1.2 如何实现记忆化搜索 1.3 记忆化搜索与动态规划的区别 2、算法应用【leetcode】 2.1 题一&#xff1a;斐波那契数 2.1.1 递归暴搜解法代码 2.1.2 记忆化搜索解法代码 2.1.3 动态规划解法代码 2.2 题二&#xff1…

vue-使用refs取值,打印出来是个数组??

背景&#xff1a; 经常使用$refs去获取组件实例&#xff0c;一般都是拿到实例对象&#xff0c;这次去取值的时候发现&#xff0c;拿到的竟然是个数组。 原因&#xff1a; 这是vue的特性,自动把v-for里面的ref展开成数组的形式&#xff0c;哪怕你的ref名字是唯一的&#xff01…

后台数据管理系统 - 项目架构设计-Vue3+axios+Element-plus(0916)

接口文档: https://apifox.com/apidoc/shared-26c67aee-0233-4d23-aab7-08448fdf95ff/api-93850835 接口根路径&#xff1a; http://big-event-vue-api-t.itheima.net 本项目的技术栈 本项目技术栈基于 ES6、vue3、pinia、vue-router 、vite 、axios 和 element-plus http:/…

6.C++程序中的基本数据类型

数据类型是指在C中用于声明不同类型变量或函数的一个系统或抽象或者是一个分类&#xff0c;它决定了变量存储占用的内存空间以及解析存储的位模式。其实数据类型可以理解为固定内存大小的别名&#xff0c;是创建变量的模具&#xff0c;具体使用哪种模具&#xff08;包括自定义&…

Python安装不再难!全平台保姆级教程带你轻松搞定!

Python介绍 Python是一种功能强大且灵活的编程语言&#xff0c;被广泛应用于各个领域。以下是Python在不同应用领域的一些常见用途&#xff1a; 网络开发 Python提供了丰富的库和框架&#xff0c;使其成为网络开发的理想选择。诸如Django、Flask和Pyramid等框架可以帮助开发人员…

一张图解析FastAdmin中的表格列表(bootstrap-table)的功能(备份)

功能描述 请根据图片上的数字索引查看对应功能说明。 1.菜单名称和描述 默认生成的CRUD是没有菜单名称和描述显示的&#xff0c;如果需要显示则可以修改权限管理->菜单规则&#xff0c;给对应菜单的添加上备注信息后即可显示&#xff0c;支持HTML 2.TAB过滤选项卡 在一键…

Linux之CentOS 7.9-Minimal部署Oracle 11g r2 安装实测验证(桌面模式)

前言: 发个之前的库存… Linux之CentOS 7.9-Minimal部署Oracle 11g r2 安装实测验证(桌面模式) 本次验证的是CentOS_7_Minimal-2009桌面模式来部署Oracle 11g r2,大家可根据自身环境及学习来了解。 环境:下载地址都给你们超链好了 1、Linux系统镜像包: 1.1 CentOS-7-x86_…