通过源码分析View的测量
要理解View的测量,首先要了解MeasureSpec,系统在测量view的宽高时,要先确定MeasureSpec。
MeasureSpec(32为int值)由两部分组成:
SpecMode(高2位):测量模式。
SpecSize(低30位):某种测量模式下的规格大小。
SpecMode有3类:
UNSPECIFIED: 父容器不对view做大小限制,一般用于系统内部,表示一种测量状态。
EXACTLY:精确模式。对应于:LayoutPrams中的match_parent和具体数值。
AT_MOST:最大值模式。对应于LayoutParam中的wrap_content模式。
接下来我们看看View的onMeasure方法:
/**
* <p>
* Measure the view and its content to determine the measured width and the
* measured height. This method is invoked by {@link #measure(int, int)} and
* should be overridden by subclasses to provide accurate and efficient
* measurement of their contents.
* </p>
*
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
}
该方法是由measure来调用的,view宽高的测量值最终是通过setMeasuredDimension来设置,具体实现不去深究。
我们看看getDefaultSize方法:
/**
* Utility to return a default size. Uses the supplied size if the
* MeasureSpec imposed no constraints. Will get larger if allowed
* by the MeasureSpec.
*
* @param size Default size for this view
* @param measureSpec Constraints imposed by the parent
* @return The size this view should be.
*/
public static int getDefaultSize(int size, int measureSpec) {
int result = size;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec); switch (specMode) {
case MeasureSpec.UNSPECIFIED:
result = size;
break;
case MeasureSpec.AT_MOST:
case MeasureSpec.EXACTLY:
result = specSize;
break;
}
return result;
}
先从MeasureSpec中获取的测量模式specMode和该模式下的大小specSize,然后对测量模式进行判断,如果是UNSPECIFIED,那么结果就是参数size,对于这个size是什么等会讨论。如果是AT_MOST和EXACTLY,那么结果就是view测量后的大小specSize。
那么这个参数size到底是什么呢?它是由实参getSuggestedMinimumWidth()和getSuggestedMinimumHeight()传下来的,我们进去getSuggestedMinimumWidth()看看。
/**
* Returns the suggested minimum width that the view should use. This
* returns the maximum of the view's minimum width)
* and the background's minimum width
* ({@link android.graphics.drawable.Drawable#getMinimumWidth()}).
* <p>
* When being used in {@link #onMeasure(int, int)}, the caller should still
* ensure the returned width is within the requirements of the parent.
*
* @return The suggested minimum width of the view.
*/
protected int getSuggestedMinimumWidth() {
return (mBackground == null) ? mMinWidth : max(mMinWidth, mBackground.getMinimumWidth());
}
从代码我们可以看出如果该view设置了背景,那么就返回max(mMinWidth, mBackground.getMinimumWidth()),否则返回mMinWidth。
mMinWidth是什么呢?它是对应android:minWidth这个属性的值,若是不指定,那么默认为0.
max(mMinWidth, mBackground.getMinimumWidth()):返回mMinWidth和mBackground.getMinimumWidth()两者中的最大值。
mBackground.getMinimumWidth()的代码如下:
/**
* Returns the minimum width suggested by this Drawable. If a View uses this
* Drawable as a background, it is suggested that the View use at least this
* value for its width. (There will be some scenarios where this will not be
* possible.) This value should INCLUDE any padding.
*
* @return The minimum width suggested by this Drawable. If this Drawable
* doesn't have a suggested minimum width, 0 is returned.
*/
public int getMinimumWidth() {
final int intrinsicWidth = getIntrinsicWidth();
return intrinsicWidth > 0 ? intrinsicWidth : 0;
}
它返回的是Drawable的原始宽度,如果Drawable有原始宽度的话。否则返回0.
因此若view有设置背景,那么size就是android:minWidth和背景最小宽度这两者的最大值,若没有设置背景,那么size的值就是android:minWidth的值。
通过源码分析View的测量的更多相关文章
- 通过源码分析Java开源任务调度框架Quartz的主要流程
通过源码分析Java开源任务调度框架Quartz的主要流程 从使用效果.调用链路跟踪.E-R图.循环调度逻辑几个方面分析Quartz. github项目地址: https://github.com/t ...
- 通过源码分析MyBatis的缓存
前方高能! 本文内容有点多,通过实际测试例子+源码分析的方式解剖MyBatis缓存的概念,对这方面有兴趣的小伙伴请继续看下去~ MyBatis缓存介绍 首先看一段wiki上关于MyBatis缓存的介绍 ...
- 从Android源码分析View绘制
在开发过程中,我们常常会来自定义View.它是用户交互组件的基本组成部分,负责展示图像和处理事件,通常被当做自定义组件的基类继承.那么今天就通过源码来仔细分析一下View是如何被创建以及在绘制过程中发 ...
- Kafka详解六:Kafka如何通过源码实现监控
问题导读: 1.kafka的消费者组的消费偏移存储,kafka支持两个版本? 2.ConsumerOffsetChecker类的作用是什么? 3.Kafka如何通过源码实现 ...
- 通过源码了解ASP.NET MVC 几种Filter的执行过程
一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神的工作,而且很多人觉得平时根本不需要知道这些,会用就行了.其实阅读源 ...
- 通过源码了解ASP.NET MVC 几种Filter的执行过程 在Winform中菜单动态添加“最近使用文件”
通过源码了解ASP.NET MVC 几种Filter的执行过程 一.前言 之前也阅读过MVC的源码,并了解过各个模块的运行原理和执行过程,但都没有形成文章(所以也忘得特别快),总感觉分析源码是大神 ...
- Linux下通过源码编译安装程序
本文简单的记录了下,在linux下如何通过源码安装程序,以及相关的知识.(大神勿喷^_^) 一.程序的组成部分 Linux下程序大都是由以下几部分组成: 二进制文件:也就是可以运行的程序文件 库文件: ...
- 在centos6.7通过源码安装python3.6.7报错“zipimport.ZipImportError: can't decompress data; zlib not available”
在centos6.7通过源码安装python3.6.7报错: zipimport.ZipImportError: can't decompress data; zlib not available 从 ...
- 通过源码编译安装VIM
开发中使用的是Ubuntu 12.04 LTS,通过sudo apt-get install vim安装的版本较低,不支持YCM,所以,用源码编译并安装最新的Vim. 卸载旧版本的Vim: sudo ...
随机推荐
- 阿里启动新项目:Nacos,比 Eureka 更强!
什么是 Nacos? Nacos 是阿里巴巴推出来的一个新开源项目,这是一个更易于构建云原生应用的动态服务发现.配置管理和服务管理平台. Nacos 致力于帮助您发现.配置和管理微服务.Nacos 提 ...
- python基础-列表(7)
一.列表格式 列表名 = [列表元素1,列表元素2,列表元素3,… ] 说明: 列表元素之间是有顺序的,也是通过下标表示,第一个元素的小标为0. 列表元素可以不是同种类型,任何类型都行 列表通常当做容 ...
- JavaScript中的原型链原理
工作中经常解除到prototype的概念,一开始错误的认为prototype是对象的原型链,其实prototype只能算是JavaScript开放出来的原型链接口,真正的原型链概念应该是__proto ...
- mysql 开发进阶篇系列 1 SQL优化(show status命令)
一.概述 随着上线后,数据越来越多,很多sql语句开始显露出性能问题,本章介绍在mysql中优化sql语句的方法. 1. 通过show status 命令了解各种sql的执行频率 通过show [ ...
- Android--UI之Gallery
前言 这篇博客讲解一下Android开发中,Gallery控件的使用,这是一个画廊视图,用于展示一组图片,用固定在中间位置的水平滚动列表显示列表项的视图.Android最新的API文档中了解到,在An ...
- 项目实战3—实现基于Keepalived+LVS的高可用集群网站架构
实现基于Keepalived高可用集群网站架构 环境:随着业务的发展,网站的访问量越来越大,网站访问量已经从原来的1000QPS,变为3000QPS,目前业务已经通过集群LVS架构可做到随时拓展,后端 ...
- 开源任务调度平台elastic-job-lite源码解析
前段时间写过一遍文章<一文揭秘定时任务调度框架quartz>,有读者建议我再讲讲elastic-job这个任务调度框架,年末没有那么忙,就来学习一下elastic-job. 首先一点,el ...
- springboot情操陶冶-@Conditional和@AutoConfigureAfter注解解析
承接前文springboot情操陶冶-@Configuration注解解析,本文将在前文的基础上阐述@AutoConfigureAfter和@Conditional注解的作用与解析 1.@Condit ...
- Go语言的map如何判断key是否存在
判断方式为value,ok := map[key], ok为true则存在 package main import "fmt" func main() { demo := map[ ...
- .Net Core实现记录接口执行时间的中间件
项目中有时接口访问时间过长,但是通过浏览器F12查看时,接口访问时间很正常,所以就很奇怪,于是写一个中间件,记录所有接口访问时间的中间件. 一.中间件 中间件是应用程序处理管道中的组件,用来处理请求和 ...