很多时候,我们需要给 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 计算:
当 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方法如下:
childWidthMeasureSpec 是 parentWidthMeasureSpec 获得的
滚动方向 childHeightMeasureSpec 其模式是 UNSPECIFIED
可以查看 HorizontalScrollView 源码刚好相反