View的绘制过程

简介: View的绘制过程从Activity.setContentView开始经过如下方法:Activity.setContentView—>PhoneWindow.

View的绘制过程从Activity.setContentView开始经过如下方法:

Activity.setContentView—>PhoneWindow.setContentView—>ViewRootImpl.requestLayout—>ViewRootImpl.scheduleTraversals—>ViewRootImpl.TraversalRunnable—>ViewRootImpl. doTraversal—>ViewRootImpl. performTraversals—>ViewRootImpl.performMeasure—>ViewRootImpl. performLayout—>ViewRootImpl. performDraw

img_15943f98c909d749e456599c77f7c8c2.png
View绘制过程

Measure

测量View的大小,从ViewRootImpl.measureHierarchy开始,计算各个控件显示需要多大的尺寸。

img_ce850dd72b9124b0d00c1dee40793bc5.png
ViewRootImpl.measureHierarchy

其中getRootMeasureSpec用来获取根布局的MeasureSpec,MeasureSpec封装了从父容器传递给子容器的布局要求,而不是父容器对子容器的布局要求,更精确的说法是,MeasureSpec是由父View的MeasureSpec和子View的LayoutParams通过计算得出的一个针对子View的测量要求,这个测量要求就是MeasureSpec。类似于下图,由一个32位的整型将mode和size包装起来。

img_b4a08a4fe27bf028ecdb36a2432e5e9c.png
MeasureSpec

MeasureSpec一共有三种模式,UNSPECIFIED(mode=0),父容器对于子容器大小没有任何限制,子容器想要多大就多大;EXACTLY(mode=-1):父容器已经为子容器设置了尺寸,子容器无论想要多大空间,都应该服从父容器指定的边界;AT_MOST(mode=-2):子容器可以是父容器指定边界内的任意大小。

img_263bdb15c79f97fd16ebb6fe95a3697a.png
ViewRootImpl.getRootMeasureSpec

根布局直接根据自己width和height属性计算MeasureSpec,MATCH_PARENT说明父布局的大小就是窗口大小,mode就是EXACTLY;WRAP_CONTENT说明根布局的最大尺寸就是窗口的尺寸,mode为AT_MOST。

在计算出Root的MeasureSpec后就通过performMeasure来调用DectorView的measure方法,该方法计算出View的大小,参数是父View对它的宽高约束,实际的测量工作是在onMeasure方法中进行的,对于DectorView就是调用FrameLayout的onMeasure方法。

img_6ddc6fabf66530cf6ec9497b6199d468.png
FrameLayout.onMeasre

FrameLayout是ViewGroup的子类,有个View[]类型的成员变量mChildren,在上图的源码中,首先调用measureChildWithMargin方法对所有子View进行一遍策略,计算所有子View的最大宽度和高度。寄过一系列计算后得到maxHeight和maxWidth。measureChildWithMargin是ViewGroup的方法,如下所示,通过调用View.measure方法。

img_6bbc9099c6a9267f330a74ffa25747b4.png
measureChildWithMargin

在measure child的时候,需要传入对子view的MeasureSpec限制,通过getChildMeasureSpec可以计算ViewGroup对子View的Spec限制,计算方式如下,根据父View的MeasureSpec和子View的LayoutParams生成子View的MeasureSpec的过程,子View的LayoutParam表示子View期待的大小。

img_ce85561f4f4a56bfdd520596b66e8bb1.png
img_4688a377f179c8d65073867f2252d86a.png
getChildMeasureSpec

以上代码分为以下几种情况:

1、父View的MeasureSpec为EXACTLY

如果childDimension>0,说明给子View指定了具体的大小,那么子View的mode为EXACTLY,size为childDimension;如果childDimension=MATH_PARENT,那么子View就是父View的Size,所以子View的Mode为EXACTLY,Size就是父View的Size;如果childDimension=WRAP_CONTENT,那么子View的最大Size为父View的Size,所以子View的Mode为AT_MOST,Size就是父View的Size

2、父View的MeasureSpec为AT_MOST

表示父View限制了子View最大为Size,如果childDimension>0,说明给子View指定了具体的大小,那么子View的Mode为EXACTLY,Size为childDimension;如果childDimension=MATH_PARENT,那么子View想和父View一样大,Mode就是AT_MOST,Size就是父View的Size;如果childDimension=WRAP_CONTENT,子View想要自己决定尺寸,但不能比父View大,Mode就是AT_MOST,Size就是父View的Size。

child.measure过程如下:

img_cfe4669effc74af2f210c0168642b669.png
View.measure

在调用了measureChildWithMargin方法后,获取到子View的MeasureSpec,接下来就调用子View的measure,并将MeasureSpec传进入, 最终调用onMeasure方法,并通过setMeasureDimension进行设置。

在Measure结束后就运行ViewRootImpl.performLayout,最后运行onLayout;之后运行performDraw,运行View的onDraw方法。

目录
相关文章
|
机器学习/深度学习 PyTorch 算法框架/工具
Pytorch使用VGG16模型进行预测猫狗二分类
深度学习已经在计算机视觉领域取得了巨大的成功,特别是在图像分类任务中。VGG16是深度学习中经典的卷积神经网络(Convolutional Neural Network,CNN)之一,由牛津大学的Karen Simonyan和Andrew Zisserman在2014年提出。VGG16网络以其深度和简洁性而闻名,是图像分类中的重要里程碑。
735 0
|
开发工具 C++ git
vs 2022与GitHub同步
vs 2022与GitHub同步
414 0
|
消息中间件 存储 算法
RocketMQ 重试机制详解及最佳实践
本文主要介绍在使用 RocketMQ 时为什么需要重试与兜底机制,生产者与消费者触发重试的条件和具体行为,如何在 RocketMQ 中合理使用重试机制,帮助构建弹性,高可用系统的最佳实践。
1729 0
RocketMQ 重试机制详解及最佳实践
|
Java 开发者 fastjson
|
SQL 数据库
初识MDL锁
初识MDL锁
264 1
|
存储 SpringCloudAlibaba NoSQL
九.SpringCloudAlibaba极简入门-持久化Sentinel限流规则
在前两章节我们学习了通过[Sentinel的限流和熔断机制](https://blog.csdn.net/u014494148/article/details/105484410)来保护微服务,提高系统的可用性,但是有一个问题,我们在Sentinel配置了限流,熔断策略,默认情况下Sentinel的数据是基于内存存储,当客户端断开,或者Sentinel重启数据就会丢失,这不是我们愿意看到的。所有我们需要的Sentinel做数据持久。 Sentinel 中支持5种持久化的方式:file、redis、nacos、zk和apollo,本片文章针对于Nacos进行持久化配置。
|
缓存 JSON API
构建高效RESTful API的最佳实践
构建高效RESTful API的最佳实践
129 0
|
存储 安全 算法
网络防御先锋:揭秘网络安全漏洞与加固信息防线
【5月更文挑战第15天】在数字时代的风口浪尖,网络安全已成为维护信息完整性、确保数据流通安全的关键。本文将深入探讨网络安全中存在的漏洞、加密技术的进展以及提升安全意识的重要性,旨在为读者构建一道坚固的信息防线提供知识支持和实践指导。
173 2
|
开发框架 Android开发 开发者
移动应用开发的未来趋势:跨平台框架与原生系统的融合
【5月更文挑战第27天】随着科技的不断进步,移动应用开发正经历着前所未有的变革。本文将探讨移动应用开发的新趋势——跨平台框架与原生系统的融合,以及这一趋势如何影响开发者、企业及最终用户。通过分析当前移动操作系统的局限性和跨平台技术的优势,我们将揭示这一融合对移动应用生态系统的潜在影响。