一次对layout_weight和match_parent的深入探究

Author Avatar
Reborn 10月 10, 2018
  • 在其它设备中阅读本文章

背景

昨晚,我又被奕广大佬日常拖去讨论问题(可以,这宿舍很好学🌚)。

这次讨论的问题是关于 Android 中 layout_weight(权重) 的用法,然后在这过程中,我们遇到了一个坑——关于权重的计算问题。

这问题可能比较基础,但是咧,我之前一直都不会用 layout_weight 的,所以是属于 layout_weight 使用的新手,大佬请绕道勿喷😂

layout_weight 的分析

权重分配的是哪些空间?

首先要明白权重分配的是哪些空间?

权重是按照比例分配屏幕的剩余空间,对这句话不理解的可以看下图:
layout_weight analyse

假如我们希望剩余的空间平分给空间1 和空间2 ,

我们分别在2个控件的设置android:layout_weight="1"

计算原理

然后我们来说下 layout_weight 的计算原理:

控件的尺寸 = 设置的控件尺寸 + 剩余空间中控件的百分比

详细的计算方式则为:

控件的宽(高)度 = 控件 的 width(height) + 控件的 weight * [父布局(LinearLayout)的宽(高)度-所有控件所占宽(高)的和] / weightSum

其中,

控件的 weight / weightSum 就是权重比;

父布局(LinearLayout)的宽(高)度-所有控件所占宽(高)的和为剩余可分配空间

补充:

  • android:layout_weight的真实含义是:一旦 View 设置了该属性(假设有效的情况下),那么该 View的宽度等于原有宽度(android:layout_width)加上剩余空间的占比!
  • 如果 width 设置了 match_parent ,那么,加上的是负的长度(相当于减去一部分长度)
  • 如果 width 设置了 wrap_content,那么,剩余空间是“父容器总长度”减去“组件的内容占的长度”,然后再按比重值分。

遇到的问题

我们遇到的是以下代码:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent">    
    <Button        
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="0dp"    
        android:text="button1" />    

    <Button 
        android:layout_weight="1"       
        android:layout_width="match_parent"     
        android:layout_height="match_parent"    
        android:text="button2" />
</LinearLayout>

然后我跟奕广就蒙圈了,为啥两个都是match_parent或0dp的时候控件可以各占一半,
both match or 0dp

而一个是 0dp 和 一个是 match_parent 却不能,反倒被button2给覆盖了?
bt1 0dp bt2  match

后来知道计算方法之后算了一下,又蒙了,算不对,我们是这样算的:
根据公式:

控件的宽(高)度 = 控件 的 width(height) + 控件的 weight * [父布局(LinearLayout)的宽(高)度-所有控件的宽(高)的和] / weightSum

得计算过程:

设父布局为1列(宽)x2行(高),则对半分之后每个控件的布局为1列(宽)x1行(高),所以每个控件的实际高度应该为1行,得:

Button2的实际显示高度 = 1行 + 1weight * (2-1-1)行 / (1+1)weight = 1行 < 2行 (错)

很明显,我们的正确答案应该是算到Button2实际显示的 2 行才是正确的,但是现在算到了 1 行,所以显然是算错了。


研究了很久才发现我们对 match_parent 的理解错了😂。

☆☆接下来是重点!!!☆☆
从计算过程中可以看出,我们认为,match_parent的实际值是 1 行。实则不然,match_parent是铺满父布局的宽(高),那么父布局为1列(宽)*2行(高)的话,match_parent的值应为 2 行!!


我们再算一遍:

设父布局为1列(宽)x2行(高),则对半分之后每个控件的布局为1列(宽)x1行(高),但

由于Button2的高度设置了match_parent,所以Button2设置的高度应该为2行,得:

Button2的实际显示高度 = 2行 + 1weight * (父布局2-2-0)行 / (1+1)weight = 2-0行 = 2行

由于Button1的高度设置了 0dp,所以Button1设置的高度应该为0行,得:

Button1的实际显示高度 = 0行 + 1weight * (2-2-0)行 / (1+1)weight = 0+0行 = 0行

这样数据就符合实际显示的效果了,完~

参考