andrid layout_weight 计算 分析

学习android以来,对于layout_weight属性一直很迷惑,感觉网上多都不靠谱,全是凭实验试出来的规律。于是就看了下源码才恍然大悟。废话不多说了直入主题。
[b]源码(有省略)[/b]
LinearLayout类中

void measureHorizontal(int widthMeasureSpec, int heightMeasureSpec) {
。。。。。。。。。。。。
float totalWeight = 0;//总的权重
[color=red] final int count = getVirtualChildCount();//子控件个数[/color]
。。。。。。。。。。。
for (int i = 0; i < count; ++i) {//依次遍历每一个控件
final View child = getVirtualChildAt(i);

if (child == null) {
mTotalLength += measureNullChild(i);//计算控件总长度
continue;
}

。。。。。。。。。。

if (hasDividerBeforeChildAt(i)) {
mTotalLength += mDividerWidth;//计算控件总长度
}

final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
child.getLayoutParams();

[color=red]totalWeight += lp.weight;//计算总的权重[/color]
。。。。。。。。。。。

。。。。。。。。
int delta = widthSize - mTotalLength;//计算剩余空间(可为负数,widthSize为layout宽度)

if (delta != 0 && totalWeight > 0.0f) {//如果剩余空间不为0,且有权重从新计算大小
float weightSum = mWeightSum > 0.0f ? mWeightSum : totalWeight;
。。。。。。。。。。。。。
mTotalLength = 0;

for (int i = 0; i < count; ++i) {
final View child = getVirtualChildAt(i);
。。。。。。。。。。。。。。
final LinearLayout.LayoutParams lp =
(LinearLayout.LayoutParams) child.getLayoutParams();

float childExtra = lp.weight;
if (childExtra > 0) {//如果子控件有权重且大于0,则分配剩余空间
// Child said it could absorb extra space -- give him his share
[color=red] int share = (int) (childExtra * delta / weightSum);//根据权重获得分配空间
weightSum -= childExtra;//总权重减去已分配的控件的权重
delta -= share;//总的剩余空间减去已分配的剩余空间[/color]

。。。。。。。。
//根据分配到的空间从新计算子控件的宽度
if ((lp.width != 0) || (widthMode != MeasureSpec.EXACTLY)) {
// child was measured once already above ... base new measurement
// on stored values
int childWidth = child.getMeasuredWidth() + share;
if (childWidth < 0) {
childWidth = 0;
}

child.measure(
MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY),
childHeightMeasureSpec);
} else {
// child was skipped in the loop above. Measure for this first time here
child.measure(MeasureSpec.makeMeasureSpec(
share > 0 ? share : 0, MeasureSpec.EXACTLY),
childHeightMeasureSpec);
}

// Child may now not fit in horizontal dimension.
。。。。。。。
}

。。。。。。
。。。。。。。。。。。




[b]总结:[/b]
注意红字部分。
layout_weight的控件的计算流程(注意:weightsum为浮点数,作为除数时不会抛异常)
1:遍历每一个控件,计算控件的大小,记录总的权重,总的空间大小和。
2:计算剩余空间(可以为负数)
3:再次遍历每个控件,更具权重从新计算控件大小。
3.1:取一个控件,计算分配到的剩余空间
share = (int) (childExtra * delta / weightSum);
3.2 总的剩余空间减去已分配的
delta -= share
3.3 总的权重减去已经分配的控件的
weightSum -= childExtra;
3.4重复3.1

[b]例子:[/b]
假设:3个Button的比例应该为1:1:2,三个按钮的宽度都是FILL_PARENT,layout宽度为一个屏幕宽度width。
所以:
[color=blue]第一次计算[/color] button1的宽度是width,button2的宽度是width,button3的宽度是width.
总长度 totalLength = 3*width;
总权重 totalWeight = 1+1+2 = 4;
屏幕空间 为 widthSize = width
剩余空间 delta = widthSize -totalLength = widh - 3*width = -2*width;
[color=blue]第二次计算[/color]
[color=cyan]根据权重再次计算button1宽度[/color]
分配剩余空间空间 share = delta*1/totalWeight = (-2*wdth)*1/4=-width/2;
button1的宽度buttonwidth 为第一次计算的宽度width加上分配到的剩余空间即 width+(-width/2)= width/2;
从新计算剩余空间和权重和
delta = delta - share = -3/2*width
totalWeight = totalWeight - button1的 weight = 4-1=3
[color=cyan]根据权重再次计算button2宽度[/color]
分配剩余空间空间 share = delta*1/totalWeight = (-3/2*wdth)*1/3=-width/2;
button2的宽度buttonwidth 为第一次计算的宽度width加上分配到的剩余空间即 width+(-width/2)= width/2;
从新计算剩余空间和权重和
delta = delta - share = -3/2*width + width/2 = -width
totalWeight = totalWeight - button2的 weight = 2-1=2
[color=cyan]根据权重再次计算button3宽度[/color]
分配剩余空间空间 share = delta*1/totalWeight = (-wdth)2/2=-width;
button3的宽度buttonwidth 为第一次计算的宽度width加上分配到的剩余空间即 width+(-width)= 0;
从新计算剩余空间和权重和
delta = delta - share = -width + width = 0
totalWeight = totalWeight - button3的 weight = 2-2=0
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值