1.前言

自定义View中我们看到很多都重写了onMeasure方法,那么我们首先得知道onMeasure是做什么的。onMeasure中文意思就是测量,所以它是用于测量View的大小,影响View大小的因素很多(父View的大小、padding、自身margin、weight),View中有一个measure方法,它会对所有View调用onMeasure方法用于测量所有View的width和height。

2.代码分析

解决自定义View占用onMeasure的部分代码:

@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); int width;
int height;
... if (widthMode == MeasureSpec.EXACTLY) {
// Parent has told us how big to be. So be it.
width = widthSize;
} else {
if (mLayout != null && mEllipsize == null) {
des = desired(mLayout);
} ...
setMeasuredDimension(width, height);

从系统View中onMeasure方法可以看到其中出现了MeasureSpec类、widthMeasureSpec和heightMeasureSpec变量,这些变量又是从什么地方产生的以及有什么用途,首先我们知道onMeasure是ViewGroup的onMeasure调用的,因此参数必定是父ViewGroup传入的,待稍后我们通过系统代码展示父ViewGroup如何产生这个参数。

3.MeasureSpec

widthMeasureSpec和heightMeasureSpec变量是用于描述View宽和高的模式与尺寸,对于measureSpec来说,其实隐含两个信息:size和mode,measureSpec是一个int类型值共32位,其中高2位用于存储mode,低30位用于存储size,我们可以通过MeasureSpec.getMode.和MeasureSpec.getSize方法进行分离,用于逻辑判断View具体需要的size。

onmeasure.png

我们知道在ViewGroup中,给View分配的控件大小并不是确定的,有可能随着具体的变化而变化,而这个变化的条件就是传给SpectMode中决定,specMode一共有三种情况:

  MeasureSpec.EXACTLY
父视图希望子视图的大小应该是父控件指定的specSize值。
MeasureSpec.AT_MOST
子视图的大小最多是specSize中指定的值,也就是说不建议子视图的大小超过specSize中给定的值。
MeasureSpec.UNSPECIFIED
我们可以随意指定视图的大小。

通过以上的这些分析,可以知道视图最终的大小由父视图,子视图以及程序员根据需求决定,良好的设计一般会根据子视图的measureSpec设置合适的布局大小。
此时有一个一问,我们XML中设置的windth和height如何对应到onMeasure中的两个参数的呢?我们用源码来进行讲解:

//ViewGroup中的获取,用不传递给ChildView
childWidthMeasureSpec = getRootMeasureSpec(desiredWindowWidth, lp.width);
childHeightMeasureSpec = getRootMeasureSpec(desiredWindowHeight, lp.height); private static int getRootMeasureSpec(int windowSize, int rootDimension) {
int measureSpec;
switch (rootDimension) { case ViewGroup.LayoutParams.MATCH_PARENT:
// Window can't resize. Force root view to be windowSize.
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.EXACTLY);
break;
case ViewGroup.LayoutParams.WRAP_CONTENT:
// Window can resize. Set max size for root view.
measureSpec = MeasureSpec.makeMeasureSpec(windowSize, MeasureSpec.AT_MOST);
break;
default:
// Window wants to be an exact size. Force root view to be that size.
measureSpec = MeasureSpec.makeMeasureSpec(rootDimension, MeasureSpec.EXACTLY);
break;
}
return measureSpec;
}

从代码中可以看出,MATCH_PARENT对应于EXACTLY,WRAP_CONTENT对应于AT_MOST,其他情况对应于EXACTLY,它和MATCH_PARENT的区别在于size值不一样。
根据以上提到的方法我们能够获得父ViewGroup允许的高度和宽度以及模式,再根据本身View的逻辑进行计算应有的宽度和模式,然后通过setMeasuredDimension方法将自身高度和宽度进行设置,则View的测量就完成。

自定义常用

在我们自定义View测量时,可能还会用到其他一些方法,如:

  • View.resolveSize(int size, int measureSpec)
    用于计算自身期望值和父视图提供值在模式下应该拥有的值,这个值可能等于自身期望值也可能低于期望值,因为父控件值影响

  • MeasureSpec.makeMeasureSpec(int size, int mode)
    用于当我们自定义ViewGroup的时候使用mode和size获得Spec

  • view.getMeasuredWidth
    用于获取View的宽度测量值

  • view.getMeasureHeight
    用于获取View的高度测量值

  • getChildMeasureSpec
    用于获取子控件的MeasureSpec值

作者:老柏的博客
链接:http://www.jianshu.com/p/ba2e73899cc7

【转载】深入剖析自定义View之onMeasure的更多相关文章

  1. 自定义View之onMeasure()

    1.自定义View之onMeasure() 2.onMeasure实例分析

  2. 转 自定义View之onMeasure()

    可以说重载onMeasure(),onLayout(),onDraw()三个函数构建了自定义View的外观形象.再加上onTouchEvent()等重载视图的行为,可以构建任何我们需要的可感知到的自定 ...

  3. 转载爱哥自定义View系列--Paint详解

    上图是paint中的各种set方法 这些属性大多我们都可以见名知意,很好理解,即便如此,哥还是带大家过一遍逐个剖析其用法,其中会不定穿插各种绘图类比如Canvas.Xfermode.ColorFilt ...

  4. android 自定义view android onmeasure onlayot ondraw

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha android onmeasure onlayot ondraw 顺序 ====== 1 ...

  5. 转载:android自定义view实战(温度控制表)!

    效果图 package cn.ljuns.temperature.view; import com.example.mvp.R; import android.content.Context;impo ...

  6. 转载爱哥自定义View系列--Canvas详解

    上面所罗列出来的各种drawXXX方法就是Canvas中定义好的能画什么的方法(drawPaint除外),除了各种基本型比如矩形圆形椭圆直曲线外Canvas也能直接让我们绘制各种图片以及颜色等等,但是 ...

  7. Android为TV端助力 转载:android自定义view实战(温度控制表)!

    效果图 package cn.ljuns.temperature.view; import com.example.mvp.R; import android.content.Context;impo ...

  8. 转载爱哥自定义View系列--文字详解

    FontMetrics FontMetrics意为字体测量,这么一说大家是不是瞬间感受到了这玩意的重要性?那这东西有什么用呢?我们通过源码追踪进去可以看到FontMetrics其实是Paint的一个内 ...

  9. Android的自定义View及View的绘制流程

    目标:实现Android中的自定义View,为理清楚Android中的View绘制流程“铺路”. 想法很简单:从一个简单例子着手开始编写自定义View,对ViewGroup.View类中与绘制View ...

随机推荐

  1. W5500 学习开发: W5500学习说明

    前言 官方已经给了大部分的例子,我只是做一下移植说明 这一节看一下如何移植官网程序的DHCP 首先先明确:单片机和W5500通信是通过SPI,所有的数据都是通过SPI接收和发送, 所以,拿到官方源码只 ...

  2. Test of String

    1.前言 这是我出的第一套题目,话说感觉有点晚了,还是在向总安排下出的.我被安排的是字符串方面的内容,这应该相对而言是比较小众的知识点吧,但是一样的有作用的,也有很神的题目.所谓是NOIP模拟题,其实 ...

  3. PATA1005Spell It Right

    考虑输入为0的特殊情况 参考代码: #define _CRT_SECURE_NO_WARNINGS #include<cstdio> #include<cstring> #in ...

  4. centos7 中没有service iptables save指令来保存防火墙规则

    解决方法: systemctl stop firewalld  关闭防火墙yum install iptables-services 安装 iptables 服务systemctl enable ip ...

  5. Mysql之配置双主热备+keeepalived.md

    准备 1 1. 双主 master1 192.168.199.49 2 master2 192.168.199.50 3 VIP 192.168.199.52 //虚拟IP 4 2.环境 master ...

  6. 特征值、特征向量与PCA算法

    一.复习几个矩阵的基本知识 1. 向量 1)既有大小又有方向的量成为向量,物理学中也被称为矢量,向量的坐标表示a=(2,3),意为a=2*i + 3*j,其中i,j分别是x,y轴的单位向量. 2)向量 ...

  7. [技术博客] JS正则活学活用

    正则基本语法 正则表达式(Regular Expression)是用单字符串来匹配一系列复合条件字符串的模式,对于乔姆斯基3型语法. 数学定义: 串行AB表示集合 {αβ | α ∈ A ,β ∈ B ...

  8. [C++基础] 数组、指针、内存篇

    一.数组 2.1 int a[2][2]= { {1}, {2,3} },则 a[0][1] 的值是多少? 二维数组的初始化一般有两种方式: 第一种方式是按行来执行,如int array\[2][3] ...

  9. Maven 教程(6)— Maven之pom.xml文件简单说明

    原文地址:https://blog.csdn.net/liupeifeng3514/article/details/79543963 通过前面几部分知识,我们对maven已经有了初步的印象,就像Mak ...

  10. php扩展模块 opcache安装教程

    php扩展模块 opcache安装教程PHP5.5.0以后版本自带Opcache加速器,但默认情况下木有启用.所以编译PHP的时候 我们想要启用该PHP加速器就应该添加参数 : –enable-opc ...