V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zpxshl
V2EX  ›  Android

为什么 xml 中 view 的最大高度是 2^23 -1

  •  
  •   zpxshl · 2021-05-08 18:52:10 +08:00 · 9035 次点击
    这是一个创建于 1324 天前的主题,其中的信息可能已经有所发展或是发生改变。

    实验观察在 xml 里面给 view 指定高度,最大为 2^23 -1 (再大的话,运行时拿到的高度就是 0 了) 为什么呢,理论上应该是 2^30 -1? 在 Android 10 的模拟器和华为测试都是这个结果

    13 条回复    2021-05-09 20:05:35 +08:00
    unixeno
        1
    unixeno  
       2021-05-08 19:18:30 +08:00 via Android
    溢出了吧
    rosu
        2
    rosu  
       2021-05-08 19:24:10 +08:00 via Android
    width 和 height 可不就是 int 型嘛...
    rosu
        3
    rosu  
       2021-05-08 19:25:02 +08:00 via Android
    然后还要转 dp 的呀,XML 读的是 dp 的值。所以要小一些。
    zpxshl
        4
    zpxshl  
    OP
       2021-05-09 00:09:15 +08:00 via Android
    @unixeno
    @rosu 用的就是 px
    int 是 32 位,这里还达不到溢出的值,另外源码里面用来表示高度的是 30 位。
    rosu
        5
    rosu  
       2021-05-09 11:24:45 +08:00   ❤️ 1
    @zpxshl 昨天在路上没认真考虑,确实回复的不对。

    刚刚看了下源码,发现是 `measureWidth` 大小直接被限制了:

    ```
    public static final int MEASURED_SIZE_MASK = 0x00ffffff;

    public final int getMeasuredWidth() {
    return mMeasuredWidth & MEASURED_SIZE_MASK;
    }
    ```

    https://cs.android.com/android/platform/superproject/+/master:frameworks/base/core/java/android/view/View.java;drc=95709ba69f9285cceb4515d86eff55793bc96eec;l=16483

    虽然 MeasureSpec 是取了 30 位。但是 `onMeasure` 时期已经被限制了大小了。无论怎么取,都只能最多拿到 3 个字节( 2^23) 的最大值。其实如果超过 2^23 也不是都是 0 。如果你试试 (2^ 24 + 1) 就会发现值为 1 。你刚好只测试了 2 的倍数,所以 AND 的低 24 位全为 0 了。

    至于为什么是 30 位,这个我就不清楚啦。
    liucccc
        6
    liucccc  
       2021-05-09 11:45:47 +08:00 via Android
    @rosu 好像是 2 位留作 mode,剩余 30 位留作 size
    rosu
        7
    rosu  
       2021-05-09 11:52:36 +08:00
    @liucccc #6 讲错。应该是 24 位。
    zpxshl
        8
    zpxshl  
    OP
       2021-05-09 12:48:46 +08:00 via Android
    @rosu 正解,感谢感谢!
    zpxshl
        9
    zpxshl  
    OP
       2021-05-09 14:20:17 +08:00 via Android
    @rosu 还有个疑惑请教下。。。。0xffffff 低 24 位均是 1,AND 这个值得出的最大值应该也是 0xffffff,2 的 24 次方...,怎么变成 2 的 23 - 1 呢,这里 and 的两个值都是 int 32 位,最高的符号位都是 0 应该不影响结果才是(低 24 位才参与运算)
    rosu
        10
    rosu  
       2021-05-09 14:32:26 +08:00 via Android
    @zpxshl 是 0x00ffffff 。高两
    2 位是零。mask 后只剩下低 24 位。而
    2^24 二进制是 25 位,低 24 位全部是 0 呀。
    rosu
        11
    rosu  
       2021-05-09 14:34:00 +08:00 via Android
    @rosu 手抖打错:0x00ffffff 高 8 位是零。其他值与之进行 and 运算后只剩下 24 位。
    zpxshl
        12
    zpxshl  
    OP
       2021-05-09 14:43:42 +08:00 via Android
    @rosu 0x00ffffff = 2^24 - 1,int 值转成二进制就是 0000 0000 1111 1111 1111 1111 1111 1111,mask 后的最大值等于自身 2^24 - 1 呀
    rosu
        13
    rosu  
       2021-05-09 20:05:35 +08:00   ❤️ 1
    @zpxshl #12 2^23 -1 的问题,怀疑和你的父 ViewGroup 有关系。我自定义布局后,重写当前尺寸(`setMeasuredDimension()`),可以设置为 2^23 。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2965 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 13:13 · PVG 21:13 · LAX 05:13 · JFK 08:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.