Android View中的onMeasure()方法详解

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

  1. MeasureSpec.UNSPECIFIED
    笔者经验不足,开发中暂时未发现什么情况下会出现
  2. MeasureSpec.EXACTLY (精确尺寸)
    当布局时layout_width、layout_height为fill_parent、macth_parent时为此值,因为子view会占据剩余容器的空间,所以它大小是确定的
  3. 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:希望本文可以帮到大家,有疑问可留言待回复

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值