Android View 如何测量
对于Android View的测量,我们一句话总结为:"给我位置和大小,我就知道您长到那里"。
为了让大家更好的理解这个结论,我这里先讲一个日常生活中的小故事:不知道大家玩过"瞎子画画"的游戏没,一个人蒙上眼睛,拿笔去画板上画一些指定的图案,另外一个人则充当他的"眼睛",通过语言告诉他在画板那个位置画一个多大的图案。倘若,这个人不告诉那个蒙着眼睛的人,在那个画一个多大的图案。那么这个蒙着眼睛的人此时真是"河里赶大车----------没辙"。其实,Android就是这个蒙着眼睛的人,我们必须精确地告诉他如何去画,它才能画出你所想要的图形。
大家是不是对Android布局的测量进行现实世界进行类比了。为了实现View具体布局在哪儿,Android设计了一个
短小精悍又功能强大的类——measureSpec类。这样妈妈再也不用担心我不会测量View了。那么,MeasureSpec到底是个什么鬼了。MeasureSpec,归根结底是一个32位的int值。其中高2位表示测量的模式,低30位表示测量View的大小。这样做有什么好处。这样做通过位运算来提高运行效率。
要了解MeasureSpec这个类的来弄去脉的话,务必要对测量的三种模式了解。
1.EXACTLY(精准的)
当您设置View的layout_height属性或layout_width属性为确定的值或者为match_parent(填充父容器)时候,系统就将View测量模式设置为EXACTLY模式。
2.AT_MOST(最大值)
即布局为最大值模式,那么什么时候系统会将View调整为AT_MOST模式了,即当您设置View的layout_height属性或layout_width属性为wrap_content(包裹内容)时候。
3.UNSPECIFIED(未确定)
即没有确定,没有指定大小测量模式,view即“心有多大,舞台就有多大"。这个方法,一般在自定义控件中才能用到。
View测量的时候,默认是EXACTLY模式,也许你会感到纳闷,TextView,EditText这些控件,他怎么就支持wrap_content属性了,难道他重写OnMeasure方法,是的,他们都重写OnMeasure方法。这就是为什么我们在自定义控件的时候,如果要布局支持wrap_content属性,就需要重写onMeasure方法,来指定wrap_content为确切的大小。
这个关于测量模式的思维导图应该是这样的:

我们知道这么多理论的知识,是不是觉得即枯燥乏味又觉得然并卵。好吧,我们就直接上代码,在代码中解释MeasureSpec如何获取测量模式和测量的大小。源代码如下:
Java代码如下:
public class MyView extends View {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
xml代码如下:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" > <com.example.test.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00ff00"
/>
</LinearLayout>
运行效果如下所示:

通过这个短小精悍的例子,充分证明这样一个结论:View测量的时候,默认是EXACTLY模式,你不重写OnMeasure方法,即使设置wrap_content属性,他也是填充父容器。
那么,就通过MeasureSpec这个万金油类来重写一下OnMeasure方法。相应源代码如下:
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(measureWidth(widthMeasureSpec),
measureWidth(heightMeasureSpec));
}
public int measureWidth(int measureSpec) {
int result = 0;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
if (specMode == MeasureSpec.EXACTLY) {
result = specSize;
} else {
result = 200;
if (specMode == MeasureSpec.AT_MOST) {
result = Math.min(specSize, result);
}
}
return result;
}
运行效果如下:

同样的例子,我们只不过是重写了OnMeasure方法,通过MeasureSpec.getMode(measureSpec)获取测量模式的时候,通过MeasureSpec.getSize(measureSpec)获取控件尺寸。判断当布局属性为wrap_content,指定为一确切值,这时,控件就符合wrap_content属性。
本文对Android如何对控件进行测量介绍,本人才疏学浅,恳请大家指教。
Android View 如何测量的更多相关文章
- Android view的测量及绘制
讲真,自我感觉,我的水平真的是渣的一匹,好多东西都只停留在知道和会用的阶段,也想去研究原理和底层的实现,可是一看到代码就懵逼了,然后就看不下去了, 说自己不着急都是骗人的,我自己都不信,前两天买了本& ...
- android View的测量和绘制
本篇内容来源于android 群英传(徐易生著) 我写到这里,是觉得徐易生讲的确实很好, 另外加入了一些自己的理解,便于自己基础的提高. 另外参考:http://www.gcssloop.com/cu ...
- 【转载】快速理解android View的测量onMeasure()与MeasureSpec
笔者之前有一篇文章已经使用onMeasure()解决了listview与scollview的显示冲突问题,博客地址如下: onMeasure简单方法 完美解决ListView与ScollView冲突问 ...
- Android View 测量流程(Measure)完全解析
前言 上一篇文章,笔者主要讲述了DecorView以及ViewRootImpl相关的作用,这里回顾一下上一章所说的内容:DecorView是视图的顶级View,我们添加的布局文件是它的一个子布局,而V ...
- Android View的绘制流程
写得太好了,本来还想自己写的,奈何肚里墨水有限,直接转吧.正所谓前人种树,后人乘凉.. View的绘制和事件处理是两个重要的主题,上一篇<图解 Android事件分发机制>已经把事件的分发 ...
- 简单研究Android View绘制三 布局过程
2015-07-28 17:29:19 这一篇主要看看布局过程 一.布局过程肯定要不可避免的涉及到layout()和onLayout()方法,这两个方法都是定义在View.java中,源码如下: /* ...
- [转]Android View.onMeasure方法的理解
转自:http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html Android View.onMeasure方法的理解 View在屏幕上显示出来要先经过 ...
- 简单研究Android View绘制一 测量过程
2015-07-27 16:52:58 一.如何通过继承ViewGroup来实现自定义View?首先得搞清楚Android时如何绘制View的,参考Android官方文档:How Android Dr ...
- Android View 如何绘制
上文说道了Android如何测量,但是一个漂亮的控件我只知道您长到哪儿,这当然不行.只需要简单重写OnDraw方法,并在Canvas(画布)对象上调用那根五颜六色的画笔就能够画出这控件"性感 ...
随机推荐
- C#winform如何最小化主窗口
1.如果不想让程序在任务栏中显示,请把窗体的属性ShowInTaskbar设置为false;2.如果想让程序启动时就最小化,请设置窗体的属性WindowState设置为Minimized.(Minim ...
- CADisplayLink以及和NSTimer的区别
什么是CADisplayLink CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器.我们在应用中创建一个新的 CADisplayLink 对象,把它添加到一个r ...
- Ubuntu上安装MongoDB(译)
add by zhj:直接从第四步开始就可以了,而且安装好MongoDB后会自动启动的,不必自己去执行启动命令 原文:https://docs.mongodb.com/manual/tutorial/ ...
- -Dmaven.multiModuleProjectDirectory system propery is not set问题解决
-Dmaven.multiModuleProjectDirectory system propery is not set问题解决 eclipse中使用maven插件的时候,运行run as mave ...
- PHPRPC jsp发布服务
PHPRPC是面向服务的高性能远程过程调用协议.PHPRPC for java 是此协议的一种实现,详细请到官方看PHPRPC的介绍 ,以其它rpc协议的性能对比请:Java.PHPRPC.Hessi ...
- Linux课程实践一:Linux基础实践(基础操作)
一.软件源维护 1. 基本操作 (1)查看源列表 sudo vim /etc/apt/sources.list deb:二进制软件安装包 deb-src:源码包 (2)备份软件源列表 sudo cp ...
- MySql Host is blocked because of many connection errors; unblock with 'mysqladmin flush-hosts' 解决方法
环境:linux,mysql5.5.21 错误:Host is blocked because of many connection errors; unblock with 'mysqladmin ...
- ffmpeg未整理好,有时间整理下
v 容器(Container) v 容器就是一种文件(封装)格式,比如flv.mkv.ts.mp4.rmvb.avi等.包含下面5种流以及文件头信息. v 流(Stream) v 是一种视频数 ...
- php 下载图片 文件
$file = dirname(dirname(__FILE__)) . $_GET['download']; //获取图片的绝对路径 header("Content-type: octet ...
- Selenium2+python自动化5-操作浏览器基本方法
前言 前面已经把环境搭建好了,这从这篇开始,正式学习selenium的webdriver框架.我们平常说的 selenium自动化,其实它并不是类似于QTP之类的有GUI界面的可视化工具,我们要学的是 ...