Android的onMeasure和onLayout And MeasureSpec揭秘
Android中自定义ViewGroup最重要的就是onMeasure和onLayout方法,都需要重写这两个方法,ViewGroup绘制 的过程是这样的:onMeasure → onLayout → DispatchDraw
- 其实我觉得官方文档解释有大大的问题,刚开始一直很疑惑onMeasure和onLayout是什么意思,看了很多资料后豁然开朗,总结如下
首先要知道ViewGroup是继承View的,后面的解释跟View有关。ViewGourp可以包含很多个View,View就是它的孩子,比如LinearLayout布局是一个ViewGroup,在布局内可以放TextEdit、ImageView等等常用的控件,这些叫子View,当然不限于这个固定的控件。
onMeasure → onLayout → DispatchDraw:onMeasure负责测量这个ViewGroup和子View的大小,onLayout负责设置子View的布局,DispatchDraw就是真正画上去了。
onMeasure
官方解释:
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- int width = MeasureSpec.getSize(widthMeasureSpec); //获取ViewGroup宽度
- int height = MeasureSpec.getSize(heightMeasureSpec); //获取ViewGroup高度
- setMeasuredDimension(width, height); //设置ViewGroup的宽高
- int childCount = getChildCount(); //获得子View的个数,下面遍历这些子View设置宽高
- for (int i = 0; i < childCount; i++) {
- View child = getChildAt(i);
- child.measure(viewWidth, viewHeight); //设置子View宽高
- }
- }
- protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) {
- boolean optical = isLayoutModeOptical(this);
- if (optical != isLayoutModeOptical(mParent)) {
- Insets insets = getOpticalInsets();
- int opticalWidth = insets.left + insets.right;
- int opticalHeight = insets.top + insets.bottom;
- measuredWidth += optical ? opticalWidth : -opticalWidth;
- measuredHeight += optical ? opticalHeight : -opticalHeight;
- }
- mMeasuredWidth = measuredWidth; //这就是保存到类变量
- mMeasuredHeight = measuredHeight;
- mPrivateFlags |= PFLAG_MEASURED_DIMENSION_SET;
- }
- public final void measure(int widthMeasureSpec, int heightMeasureSpec) {
- <span style="white-space:pre"> </span>.........
- <span style="white-space:pre"> </span>// measure ourselves, this should set the measured dimension flag back
- onMeasure(widthMeasureSpec, heightMeasureSpec);
- <span style="white-space:pre"> </span>..........
- }
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- setMeasuredDimension(getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec),
- getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec));
- }
- @Override
- protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
- int mTotalHeight = 0;
- // 当然,也是遍历子View,每个都要告诉ViewGroup
- int childCount = getChildCount();
- for (int i = 0; i < childCount; i++) {
- View childView = getChildAt(i);
- // 获取在onMeasure中计算的视图尺寸
- int measureHeight = childView.getMeasuredHeight();
- int measuredWidth = childView.getMeasuredWidth();
- childView.layout(left, mTotalHeight, measuredWidth, mTotalHeight + measureHeight);
- mTotalHeight += measureHeight;
- }
- }
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec);
- int width = MeasureSpec.getSize(widthMeasureSpec); //获取真实width
- int height = MeasureSpec.getSize(heightMeasureSpec); //获取真实height
- setMeasuredDimension(width, height); //设置ViewGroup的宽高
- for (int i = 0; i < getChildCount(); i++) {
- getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec); //遍历孩子设置宽高
- }
- }
- public static class MeasureSpec {
- private static final int MODE_SHIFT = 30; //
- private static final int MODE_MASK = 0x3 << MODE_SHIFT;
- public static int getMode(int measureSpec) {
- return (measureSpec & MODE_MASK);
- }
- public static int getSize(int measureSpec) {
- return (measureSpec & ~MODE_MASK);
- }
- }
发现解析前后的值差很远,再结合源代码 widthMeasureSpec & ~ MODE_MASK,运算后刚好匹配得到width。运算方法:0x3=0011, 它向左移位30位,得到1100 0000 .....(1后面一共有30个0.) ~取反后就是0011 1111……(0后面有30个1). 上面的widthMeasureSpec是1073742304,转换成二进制是 0100 0000 0000 0000 0000 0001 1110 0000,和前面那个 ~MODE_MASK &之后(注意MODE_MASK要先取反再与widthMeasureSpec),最前面那个2个1就去掉了,widthMeasureSpec只留下了后面一段有1,即得到0000 …(省略16个0)… 0001 1110 0000,得到的值转换成 十进制刚好是480,完美,转换后得到了真实的width。手机的屏幕刚好是480*854,这是小米1的屏幕。
Android的onMeasure和onLayout And MeasureSpec揭秘的更多相关文章
- 【转】ViewGroup的onMeasure和onLayout分析
ViewGroup的onMeasure和onLayout分析 一个Viewgroup基本的继承类格式如下: 1 import android.content.Context; 2 import and ...
- ANDROID自己定义视图——onLayout源代码 流程 思路具体解释
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 简单介绍: 在自己定义view的时候.事实上非常easy.仅仅须要知道3步骤: 1.測量- ...
- 继承ViewGroup学习onMeasure()和onLayout()方法
在继承ViewGroup类时,需要重写两个方法,分别是onMeasure和onLayout. 1,在方法onMeasure中调用setMeasuredDimension方法void android.v ...
- 通过重写ViewGroup学习onMeasure()和onLayout()方法
在继承ViewGroup类时,需要重写两个方法,分别是onMeasure和onLayout. 1,在方法onMeasure中调用setMeasuredDimension方法 void android. ...
- [转]Android View.onMeasure方法的理解
转自:http://blog.sina.com.cn/s/blog_61fbf8d10100zzoy.html Android View.onMeasure方法的理解 View在屏幕上显示出来要先经过 ...
- 自定义控件详解(五):onMeasure()、onLayout()
前言: 自定义控件的三大方法: 测量: onMeasure(): 测量自己的大小,为正式布局提供建议 布局: onLayout(): 使用layout()函数对所有子控件布局 绘制: onDraw() ...
- Android下如何理解onMeasure,onLayout的过程
在Android中view如何完成绘制这个过程介绍了很多,但是很多理论化的东西,最近重新整理一下,通俗的讲解一下. View绘制过程就好比你向银行贷款, 在执行onMeasure的时候,好比银行告诉你 ...
- Android onMeasure 方法的测量规范MeasureSpec
一个MeasureSpec封装了父布局传递给子布局的布局要求,每个MeasureSpec代表了一组宽度和高度的要求.一个MeasureSpec由大小和模式组成.它有三种模式:UNSPECIFIED(未 ...
- android自定义控件 onMeasure() 测量尺寸
上次讲的自定义控件刷新点屏幕的任意地方都会刷新,而且在xml里自定义控件下面放一个textview的话,这个TextView是显示不出来的,不只这个,以前的几个自定义控件都是 为什么呢?今天来讲下on ...
随机推荐
- IO中同步、异步与阻塞、非阻塞的区别
一.同步与异步同步/异步, 它们是消息的通知机制 1. 概念解释A. 同步所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回. 按照这个定义,其实绝大多数函数都是同步调用(例如si ...
- 洛谷 P1379 八数码难题 Label:判重&&bfs
特别声明:紫书上抄来的代码,详见P198 题目描述 在3×3的棋盘上,摆有八个棋子,每个棋子上标有1至8的某一数字.棋盘中留有一个空格,空格用0来表示.空格周围的棋子可以移到空格中.要求解的问题是:给 ...
- APP测试流程
1 APP测试基本流程 1.1流程图 1.2测试周期 测试周期可按项目的开发周期来确定测试时间,一般测试时间为两三周(即15个工作日),根据项目情况以及版本质量可适当缩短或延长测试时间.正式测试前先向 ...
- 【POJ】2891 Strange Way to Express Integers
http://poj.org/problem?id=2891 题意:求最小的$x$使得$x \equiv r_i \pmod{ a_i }$. #include <cstdio> #inc ...
- Android -- 自定义ImageView(圆形头像)
1. 原图
- OSG动画学习
OSG动画学习 转自:http://bbs.osgchina.org/forum.php?mod=viewthread&tid=3899&_dsign=2587a6a9 学习动画,看了 ...
- [CareerCup] 17.4 Maximum of Two Numbers 两数中的较大值
17.4 Write a method which finds the maximum of two numbers. You should not use if-else or any other ...
- Hadoop.2.x_网站PV示例
一.网站基本指标(即针对于网站用户行为而产生的日志中进行统计分析) 1. PV:网页浏览量(Page View页面浏览次数,只要进入该网页就产生一条记录,不限IP,统计点每天(较多)/每周/每月/.. ...
- Unique Binary Search Trees
Given n, how many structurally unique BST's (binary search trees) that store values 1...n? For examp ...
- CentOS碰到两个问题,顺便解决了下
1.弹出界面 eth0: RTNETLINK answers: File exists 执行service network restart时报的错误 因为service network start造成 ...