Something about measure
来源:互联网 发布:c语言if条件语句 编辑:程序博客网 时间:2024/05/17 23:43
在Android开发中,与View相关的理解中有三个过程比较重要,也比较难理解,这里简单说一下与Measure相关的问题:
Measure的作用:
Measure这个流程主要作用是将布局中诸如一些MATCH_PARENT、WRAP_CONTENT结合View自身的特点要求,获取View最终大小的这么一个过程。举一个简单例子,你一个手机宽为600像素,你的TextView和上层布局的layout_width都是MATCH_PARENT,那你最终的TextView会在横向上都充满屏幕,在这个Measure的流程中,TextView控件最终会设置宽度为600像素。在Measure的过程中有几个重要概念,先解释一下:
1:Measure Mode
Measure Mode主要有三类,其中主要用的是(1)、(2),他们基本的解释情况如下,至于它们如何发挥作用,与布局属性有何关联呢,后边会详细介绍:
(1)、EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;
(2)、AT_MOST(至多),子元素至多达到指定大小的值。
(3)、UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;
2:MeasureSpec
大家如果看到源码或者看开源的一些自定义的View控件时,可能经常会在onMeasure()方法中看到类似的源码:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取view长宽方向上的mode、mode类型如上边介绍
int widthMode= MeasureSpec.getMode(widthMeasureSpec);
int heightMode == MeasureSpec.getMode(heightMeasureSpec);
//获取view长宽方向的长度
int width= MeasureSpec.getSize(widthMeasureSpec);
int height=MeasureSpec.getSize(heightMeasureSpec);
.....
}
不知道到这里大家有没有疑问,为什么从widthMeasureSpec一个变量中,我们可以获取到mode和宽度两个值,不知道大家有没有这个疑问,反正我第一次看到这个代码时感觉有些怪异,对于这个问题这里先简单解释一下后边会结合源码进行详细阐述,widthMeasureSpec这个变量时一个32位的int,其中他高位的16位记录着mode、低位的16位则记录着具体的size,因此同一个值既可以获取mode也可以获取size。
3:mode与wrap_content、match_parent的关系
关于这个问题还是上源码比较清楚,在ViewRoot里有getRootMeasureSpec方法,方法实现如下:
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;
}
MeasureSpec.makeMeasureSpec()这个方法咱们下边马上可以说到,但是从源码可以看到当布局方式为WRAP_CONTENT时,mode为MeasureSpec.AT_MOST,当布局方式为MATCH_PARENT和具体的值时都为MeasureSpec.EXACTLY;
4:MeasureSpec源码
通过上边介绍我们会发现MeasureSpec类是一个重要的类,通过MeasureSpec可以获取一个控件的布局mode和size,布局文件中设置的WRAP_CONTENT、MATCH_PARENT等都会对应一个mode,接下来看看MeasureSpec的实现:
public static class MeasureSpec {
private static final int MODE_SHIFT = 30;
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
/**
* Measure specification mode: The parent has not imposed any constraint
* on the child. It can be whatever size it wants.
*/
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
/**
* Measure specification mode: The parent has determined an exact size
* for the child. The child is going to be given those bounds regardless
* of how big it wants to be.
*/
public static final int EXACTLY = 1 << MODE_SHIFT;
/**
* Measure specification mode: The child can be as large as it wants up
* to the specified size.
*/
public static final int AT_MOST = 2 << MODE_SHIFT;
/**
* Creates a measure specification based on the supplied size and mode.
*
*
* @param size the size of the measure specification
* @param mode the mode of the measure specification
* @return the measure specification based on size and mode
*/
public static int makeMeasureSpec(int size, int mode) {
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
/**
* Extracts the mode from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the mode from
*/
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
/**
* Extracts the size from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the size from
* @return the size in pixels defined in the supplied measure specification
*/
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
static int adjust(int measureSpec, int delta) {
return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec));
}
/**
* Returns a String representation of the specified measure
* specification.
*
* @param measureSpec the measure specification to convert to a String
* @return a String with the following format: "MeasureSpec: MODE SIZE"
*/
public static String toString(int measureSpec) {
int mode = getMode(measureSpec);
int size = getSize(measureSpec);
StringBuilder sb = new StringBuilder("MeasureSpec: ");
if (mode == UNSPECIFIED)
sb.append("UNSPECIFIED ");
else if (mode == EXACTLY)
sb.append("EXACTLY ");
else if (mode == AT_MOST)
sb.append("AT_MOST ");
else
sb.append(mode).append(" ");
sb.append(size);
return sb.toString();
}
}
通过源码我们可以看到makeMeasureSpec()方法,是将mode和size搞到一个int中了,同样getSize(),getMode()方法又可以将相应的size和mode进行还原
5:Tips
与measure有关的应用主要在自定义view上,主要在于如何去重写onMeasure方法,这里不在说为何需要去重写onMeasure方法,与measure具体相关的流程,网上有一堆相关博客,大家可以参考一下。在onMeasure方法的重写上又根据View和ViewGroup不同,实现方式不同,View的实现方式上主要根据onmeasure里传过来的参数获取mode和size,以及自身所需要的size进行计算合适的大小,如果是mode是exectly,则控件大小为传过来的size大小,如果mode是at_most,则控件大小为传过来的size和自身所需size的最小值即可,当然了,我们可以不用管传过来的mode和size是啥,给控件设置一个具体的大小,这样程序不会有任何问题,只是可能会在整体显示上没有那么美观。对于ViewGroup来说,在onMeasure里主要去测量子类的大小,这个根据自定义ViewGroup的不同可能实现会有差异。
Measure的作用:
Measure这个流程主要作用是将布局中诸如一些MATCH_PARENT、WRAP_CONTENT结合View自身的特点要求,获取View最终大小的这么一个过程。举一个简单例子,你一个手机宽为600像素,你的TextView和上层布局的layout_width都是MATCH_PARENT,那你最终的TextView会在横向上都充满屏幕,在这个Measure的流程中,TextView控件最终会设置宽度为600像素。在Measure的过程中有几个重要概念,先解释一下:
1:Measure Mode
Measure Mode主要有三类,其中主要用的是(1)、(2),他们基本的解释情况如下,至于它们如何发挥作用,与布局属性有何关联呢,后边会详细介绍:
(1)、EXACTLY(完全),父元素决定自元素的确切大小,子元素将被限定在给定的边界里而忽略它本身大小;
(2)、AT_MOST(至多),子元素至多达到指定大小的值。
(3)、UNSPECIFIED(未指定),父元素部队自元素施加任何束缚,子元素可以得到任意想要的大小;
2:MeasureSpec
大家如果看到源码或者看开源的一些自定义的View控件时,可能经常会在onMeasure()方法中看到类似的源码:
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//获取view长宽方向上的mode、mode类型如上边介绍
int widthMode= MeasureSpec.getMode(widthMeasureSpec);
int heightMode == MeasureSpec.getMode(heightMeasureSpec);
//获取view长宽方向的长度
int width= MeasureSpec.getSize(widthMeasureSpec);
int height=MeasureSpec.getSize(heightMeasureSpec);
.....
}
不知道到这里大家有没有疑问,为什么从widthMeasureSpec一个变量中,我们可以获取到mode和宽度两个值,不知道大家有没有这个疑问,反正我第一次看到这个代码时感觉有些怪异,对于这个问题这里先简单解释一下后边会结合源码进行详细阐述,widthMeasureSpec这个变量时一个32位的int,其中他高位的16位记录着mode、低位的16位则记录着具体的size,因此同一个值既可以获取mode也可以获取size。
3:mode与wrap_content、match_parent的关系
关于这个问题还是上源码比较清楚,在ViewRoot里有getRootMeasureSpec方法,方法实现如下:
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;
}
MeasureSpec.makeMeasureSpec()这个方法咱们下边马上可以说到,但是从源码可以看到当布局方式为WRAP_CONTENT时,mode为MeasureSpec.AT_MOST,当布局方式为MATCH_PARENT和具体的值时都为MeasureSpec.EXACTLY;
4:MeasureSpec源码
通过上边介绍我们会发现MeasureSpec类是一个重要的类,通过MeasureSpec可以获取一个控件的布局mode和size,布局文件中设置的WRAP_CONTENT、MATCH_PARENT等都会对应一个mode,接下来看看MeasureSpec的实现:
public static class MeasureSpec {
private static final int MODE_SHIFT = 30;
private static final int MODE_MASK = 0x3 << MODE_SHIFT;
/**
* Measure specification mode: The parent has not imposed any constraint
* on the child. It can be whatever size it wants.
*/
public static final int UNSPECIFIED = 0 << MODE_SHIFT;
/**
* Measure specification mode: The parent has determined an exact size
* for the child. The child is going to be given those bounds regardless
* of how big it wants to be.
*/
public static final int EXACTLY = 1 << MODE_SHIFT;
/**
* Measure specification mode: The child can be as large as it wants up
* to the specified size.
*/
public static final int AT_MOST = 2 << MODE_SHIFT;
/**
* Creates a measure specification based on the supplied size and mode.
*
*
* @param size the size of the measure specification
* @param mode the mode of the measure specification
* @return the measure specification based on size and mode
*/
public static int makeMeasureSpec(int size, int mode) {
if (sUseBrokenMakeMeasureSpec) {
return size + mode;
} else {
return (size & ~MODE_MASK) | (mode & MODE_MASK);
}
}
/**
* Extracts the mode from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the mode from
*/
public static int getMode(int measureSpec) {
return (measureSpec & MODE_MASK);
}
/**
* Extracts the size from the supplied measure specification.
*
* @param measureSpec the measure specification to extract the size from
* @return the size in pixels defined in the supplied measure specification
*/
public static int getSize(int measureSpec) {
return (measureSpec & ~MODE_MASK);
}
static int adjust(int measureSpec, int delta) {
return makeMeasureSpec(getSize(measureSpec + delta), getMode(measureSpec));
}
/**
* Returns a String representation of the specified measure
* specification.
*
* @param measureSpec the measure specification to convert to a String
* @return a String with the following format: "MeasureSpec: MODE SIZE"
*/
public static String toString(int measureSpec) {
int mode = getMode(measureSpec);
int size = getSize(measureSpec);
StringBuilder sb = new StringBuilder("MeasureSpec: ");
if (mode == UNSPECIFIED)
sb.append("UNSPECIFIED ");
else if (mode == EXACTLY)
sb.append("EXACTLY ");
else if (mode == AT_MOST)
sb.append("AT_MOST ");
else
sb.append(mode).append(" ");
sb.append(size);
return sb.toString();
}
}
通过源码我们可以看到makeMeasureSpec()方法,是将mode和size搞到一个int中了,同样getSize(),getMode()方法又可以将相应的size和mode进行还原
5:Tips
与measure有关的应用主要在自定义view上,主要在于如何去重写onMeasure方法,这里不在说为何需要去重写onMeasure方法,与measure具体相关的流程,网上有一堆相关博客,大家可以参考一下。在onMeasure方法的重写上又根据View和ViewGroup不同,实现方式不同,View的实现方式上主要根据onmeasure里传过来的参数获取mode和size,以及自身所需要的size进行计算合适的大小,如果是mode是exectly,则控件大小为传过来的size大小,如果mode是at_most,则控件大小为传过来的size和自身所需size的最小值即可,当然了,我们可以不用管传过来的mode和size是啥,给控件设置一个具体的大小,这样程序不会有任何问题,只是可能会在整体显示上没有那么美观。对于ViewGroup来说,在onMeasure里主要去测量子类的大小,这个根据自定义ViewGroup的不同可能实现会有差异。
0 0
- Something about measure
- Something about ...
- Something about float divide
- something about Tomcat(zz)
- something about Listeners
- something about Macro
- Something about Music
- something about struts
- something about ado
- something about SEO
- Something About Pretect Mode
- something about this week
- Something about Ajax
- something about Ajax Ⅱ
- Something | About db-design
- Something About ! CSS
- Something About FLV视频
- Something about WM_PAINT
- 黑马程序员—(基础加强JDK1.5)—枚举部分
- ASP.NET MD5与SHA1加密的几种方法
- sql查询表根据某列排序的任意行语句
- JS判断null、undefined与NaN的方法
- 新站刚建应该怎么样对网站优化,应该掌握哪些seo优化方法
- Something about measure
- IP 对应 网址
- Minimum Path Sum -- LeetCode
- 使用线程的消息队列
- 2013年中国软件开发者薪资调查报告
- MyEclipse编码设置,中文乱码解决方法,UTF-8,GBK
- puppet的安装和配置
- AJAX with JQuery
- AJAX with JQuery