您的位置:首页 > 移动开发 > Android开发

Android View中的onMeasure()方法详解

2015-07-17 22:43 543 查看
onMeasure()方法是哪里的?有什么用?有的人可能会有这种疑问,这里我们就来探讨下此方法

笔者上篇文章中的案例简单接触了onMeasure方法来实现方形View:Android实现正方形View

onMeasure()方法在哪里?有什么用?

void onMeasure(int widthMeasureSpec, int heightMeasureSpec);
/*
1.此方法在哪里了?
答:如标题所言,在 class View 这个类中,也就是说,我们所有的控件都有这个方法
2.有什么用了?
答:Measure the view and its content to determine the measured width and the measured height.
(测量视图及其内容,以确定所测量的宽度和测量的高度。)
*/


onMeasure()方法在什么情况下我们需要用到?怎么用?

在这之前我们需要了解一个疑问:此方法在开发的时候没有调用过啊!那此方法什么时候会被调用?

根据笔者的开发经验来看,以“on”单词开头的方法都是当什么什么时候回调的,也就是说系统在某一时刻会自动调用此方法。知道这点后就行了,就是此方法不要我们关心什么时候调用,它该出手时就出手。

——此方法中的两个参数是什么东西?

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, widthMeasureSpec);
/*获得宽度的测量模式(测量模式见下面介绍class MeasureSpec)*/
final int widthMode = MeasureSpec.getMode(widthMeasureSpec);
/*获得高度的测量模式(测量模式见下面介绍class MeasureSpec)*/
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
/*获得宽度的尺寸*/
final int widthSize = MeasureSpec.getSize(widthMeasureSpec);
/*获得高度的尺寸*/
final int heightSize = MeasureSpec.getSize(heightMeasureSpec);
}


class MeasureSpec

MeasureSpec.UNSPECIFIED

笔者经验不足,开发中暂时未发现什么情况下会出现

MeasureSpec.EXACTLY (精确尺寸)

当布局时layout_width、layout_height为fill_parent、macth_parent时为此值,因为子view会占据剩余容器的空间,所以它大小是确定的

MeasureSpec.AT_MOST (最大尺寸)

当布局时layout_width、layout_height为具体的值时为此值,因为我们已经确定了View的宽度或高度,所以它的最大尺寸是我们给的值

Public Methods

//*获得参数中的测量空间的测量模式,模式取值上面介绍的三个常量*/
static int getMode(int measureSpec);
/*获得参数中的测量空间的尺寸*/
static int getSize(int measureSpec);
/*根据传入的参数尺寸size与模式mode制造出一个测量空间值*/
static int makeMeasureSpec(int size, int mode);


情景需求

实现一个View,使它的高度等于宽度的一半,直接上关键代码

思路1:在onMeasure方法中通过MeasureSpec.getSize(int measureSpec)方法获得宽度的尺寸width,然后用获得宽度值width/2算出高度值height,然后调用setMeasuredDimension(measuredWidth,measuredHeight)实现

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightSize = widthSize/2;
setMeasuredDimension(widthSize,heightSize);
}




思路2:在onMeasure方法中通过MeasureSpec.getSize(int measureSpec)方法与MeasureSpec.getMode(int measureSpec)方法获得宽度的尺寸width与宽度的模式mode,然后用获得宽度值width/2算出高度值height,然后调用MeasureSpec.makeMeasureSpec(int size, int mode)方法将算出的高度height与取到的模式mode分别传入得到一个测量空间数据heightMeasureSpec,此值其实就是我们需要的高度测量空间值,然后我们调用super.onMeasure(widthMeasureSpec, widthMeasureSpec)实现

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int height = widthSize / 2;
int heightMode = MeasureSpec.getMode(widthMeasureSpec);
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, heightMode);
super.onMeasure(widthMeasureSpec,heightMeasureSpec);
}




两种方法有什么不同?<笔者推荐思路2>

思路1:不适用于ViewGrop,当自定义ViewGrop这样实现onMeasure()方法,子View无法显示,读者可尝试;当自定义TextView等这些控件时,比例可能会满足我们的需求,但尺寸可能会超出我们的想象,读者可尝试;

思路2:思路1中的现象都不会出现,因为我们只是通过创建一个新的测量空间重新传给父类方法,所有的计算方法我们都没有变,所以此方法是通过的

情景作业

自定义一个TextView,实现宽度是父容器宽度的一半,高度是宽度的一半

PS:希望本文可以帮到大家,有疑问可留言待回复
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息