Android自定义view的onMeasure参数MeasureSpec含义分析

本文探讨了Android自定义view的onMeasure方法中MeasureSpec的含义,指出其既不是父ViewGroup的宽高,也不是子View的宽高,而是表示了父ViewGroup对子View的期望值。在测量过程中,MeasureSpec由ViewRootImpl传递,经过一系列计算,结合父ViewGroup和子View的设定,形成一种理想值。如果不重写onMeasure,自定义view将不支持wrap_content属性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

说起Android的自定义view,各位老油条肯定都不陌生了,我也是在最近重温《安卓开发艺术探索》的时候才发现的这个问题,**onMeasure的参数 MeasureSpec 到底表示了自身的属性还是父view的属性?**我问了身边的小伙伴,他们的回答都不对或者很模棱两可,所以我特意记录一下,希望小伙伴们能有个准确地认识。

结论先行

先说下结论,onMeasure是测量view或viewGroup时系统调用的,它的参数widthMeasureSpec和heightMeasureSpec既不代表父ViewGroup的宽高也不代表子View的宽高,它表示了父ViewGroup对自己的期望,至于子View实际的宽高得看setMeasuredDimension传的是什么。

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // ...
    }

具体分析

那么什么是父view的期望值?我们从头说起,在android绘制的过程中,view树的最顶层是ViewRootImpl,它是一个实现了ViewParent接口的特殊的类,我们可以把它看成所有View的爷爷,ViewRootImpl中又存着DecorView的实例,我们知道DecorView才是我们View树最上层的ViewGroup,系统会调用ViewRootImpl的performTraversal方法开始View树的绘制,这个方法里面会调用DecorView的measure方法,到此,View的绘制正式传递到DecorView中

好,停一下,ViewRootImpl传递给DecorView的measure方法中的参数是怎么来的?我们看一下performTraversal方法内部这一小段:

    int childWidthMeasureSpec = getRootMeasureSpec(mWidth, lp.width);
    int childHeightMeasureSpec = getRootMeasureSpec(mHeight, lp.height);
     // Ask host how big it wants to be
    performMeasure(childWidthMeasureSpec, childHeightMeasureSpec);

mWidth,mHeight指的是屏幕的宽高,lp是一个LayoutParams类型的参数,他表示当前window的尺寸参数,那么也就是说这里的值都是当前屏幕的参数,关键还得看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.
  
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一杯刘

我 风暴降生 打钱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值