【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 进行计算

你可能感兴趣的:(【Android】TextView 计算高度的坑【MeasureSpec.UNSPECIFIED 注意事项】)