前言
起因是这样的,我在做底部导航栏过程中,需要等比例排列每个item,于是我用了fillMaxWidth
函数去定制item宽度,却遇到了第一个item能展示一半,第二个item展示不全的问题。
先看下fillMaxWidth
函数:
大致解读一下,这个函数需要传入一个 0.0-1.0 的一个百分比(fraction
),也就是说传入的百分比是当前item在父容器内的占比,我写了如下代码:
.fillMaxWidth(1 / tabSize.toFloat())
当前我的item个数是2个,以下代码在tabSize的情况下遍历调用。按照预期就会得到两块等比例的排列,像图中这样:
但其实我得到了如下模样:
这就比较迷惑了对吧,进入源码开始查看
排查问题
我们当前的fraction
的值两个都是 0.5,于是进入 createFillWidthModifier(fraction)
,可以看到这个函数最终调用了 FillModifier(...)
/**
* @param fraction The fraction of the maximum width to use, between `0` and `1`, inclusive.
*/
fun Modifier.fillMaxWidth(/*@FloatRange(from = 0.0, to = 1.0)*/ fraction: Float = 1f) =
this.then(if (fraction == 1f) FillWholeMaxWidth else createFillWidthModifier(fraction))
private val FillWholeMaxWidth = createFillWidthModifier(1f)
private fun createFillWidthModifier(fraction: Float) = FillModifier(
direction = Direction.Horizontal,
fraction = fraction,
inspectorInfo = {
name = "fillMaxWidth"
properties["fraction"] = fraction
}
)
找到答案
查看 FillModifier
,文档有这样一句描述出乎了预料
The maximum width that the measurement can take, in pixels.
译文:测量可以采用的最大宽度,以像素为单位。
也就是说,并非如初想象的那样(每个view各占父容器的一半宽度),而是当前view占父容器内剩余可用宽度的一半,说白了就是第一个item排列后占用了一半宽度,第二个item就只能用剩下的一半作为最大宽度了,所以第二个item传入的宽度是一半的一半,依次类推如果三四个item都会持续更小。
解决
问题找到了,解决办法就很简单了,假设当前5个item,会得到结果 1/5=0.2,每个item占0.2。
总宽度在每放置一个item后就减小一个item的宽度,总比例逐个减小,于是得到以下代码: