【Android】TextView 计算高度的坑【MeasureSpec.UNSPECIFIED 注意事项】

很多时候,我们需要给 TextView 增加展开的效果动画,那怎么计算一个没有展示出来的 TextView 的高度呢?

通常得到的方案是(Kotlin代码):

val width = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)

val height = View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED)

this.measure(width, height)

结果:this.measuredHeight

对于大多数的 View 来讲,这样没有问题。那为什么 TextView 反而有问题呢?

TextView 的 onMeasure 计算:

图1 onMeasure方法中计算宽度

当 widthMode 为 EXACTLY时,使用设置的 widthSize。

其他情况,计算宽度,此时得到的 width 值是有可能超过屏幕宽度的,因此当 widthMode == AT_MOST 的时候,对于计算出来的 width 值进行了修正,不能超过父布局设置的 widthSize。

问题一:为什么是父布局的 widthSize?

MeasureSpec 的三种模式

拿宽度举例:

EXACTLY:View 自身确定的宽度大小。布局里表现:match_parent, 具体dp值

AT_MOST:View 自身宽度不确定,此时父布局将自身可用的最大宽度传给 子View,代表 子View 的最大宽度。布局表现:wrap_content

UNSPECIFIED:可滚动 ViewGroup 给 子View 设置的。例如 ListView, ScrollView 等。

问题二:为什么 widthMode == UNSPECIFIED 时不需要进行修正呢?

因为父布局在可滚动方向上,是不需要对于该方向计算的数值进行修正的。ScrollView measureChild方法如下:

图2 ScrollView measureChild方法

childWidthMeasureSpec 是 parentWidthMeasureSpec 获得的

滚动方向 childHeightMeasureSpec 其模式是 UNSPECIFIED

可以查看 HorizontalScrollView 源码刚好相反

因此我们在使用 measure 方法时一定要注意,不能简单的使用 UNSPECIFIED 进行计算

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。