登录 立即注册
安币:

你真的了解weight和weightSum吗? [复制链接]

2018-1-9 10:38
sergiochanTest 阅读:726 评论:2 赞:1
Tag:  

看到本文的标题,很多童鞋会一脸不屑的说,这有什么不了解的。不就是通过weight来给子布局按比例来分配空间嘛!好,这个答案也对也不对。 此时有人会疑惑了,为什么也对也不对? 我先来举两个最常见的例子:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal">

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="A" />

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="B" />

</LinearLayout>

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="A" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="B" />

</LinearLayout>

Picture

这两个例子都能实现上图的效果。那么问题来了,这两个方式有什么区别吗? 眼尖的童鞋立马会说:当然有区别,一个 android:layout_width 是0, 另一个是 wrap_content。 那么这两个有什么区别吗? 为什么实现的效果是一样的? 我还要问一句,真的是一样吗?

如果对这个问题有所疑惑,那么兔子哥将带领大家来深入了解一下weight和weightSum,并通过阅读本篇文章,做到知其然,并且知其所以然。

什么是weight和weightSum

某位伟人曾经说过,要对某个知识点深入了解,最好的切入点就是仔细阅读知识点的定义。至于这位伟人是谁,什么?想不起来了?不用想了,就是这篇博文的作者,兔子哥大人也! ~~~好了,扯了这么多废话!我们还是先步入正题,先看看Google是怎么给 android:layout_weight 和 android:weightSum来定义的:

Layout Weight

to individual children with the android:layout_weight

  1. This attribute assigns an "importance" value to a view in terms of how much space it should occupy on the screen. A larger weight value allows it to expand to fill any remaining space in the parent view. Child views can specify a weight value, and then any remaining space in the view group is assigned to children in the proportion of their declared weight. Default weight is zero.

大体意思就是,android:layout_weight 这个属性代表了一个“重要性”的值,这个值的大小代表了该控件能在屏幕中占据多大的空间。这个值越大,表明该控件可以在父控件中占据较多的“剩余”空间。默认的weight是0。
在这里,大家一定要注意“剩余”两个字!大家往往容易忽略这一点,导致出现了很多问题。举个例子:水平方向布局的父类有三个子类,父类总的宽度是100,子类的宽度分别是10,20,30。 那么 android:layout_weight 这个属性的目的,就是瓜分剩余的 100 - 10 - 20 - 30,也就是剩余的40的使用权。没错! 就是android:layout_weight 这个属性 仅仅决定 哪个子类能瓜分到更多的40的部分!

android:weightSum

Defines the maximum weight sum. If unspecified, the sum is computed by adding the layout_weight of all of the children.

这个就很好理解了,weightSum定义了weight 总和的最大值。如果 android:weightSum 没有定义,那么默认值就是通过各个子类的 layout_weight 累加得到。

工作原理

讲了这么多,举个例子来说明一下。


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="horizontal"
    android:weightSum="1">

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="0.5"
        android:text="@string/hello_world" />

</LinearLayout>

效果如下图:

Picture

内部的计算原理是:
Button的宽度 = Button 的 width + Button的weight * 父布局(LinearLayout)的宽度 / weightSum
上面的例子,也就是 Button的宽度 = 0 + 0.5 * LinearLayout的宽度 / 1 = 0.5 * LinearLayout的宽度
也就是Button的宽度将占屏幕的一半。

Google官方例子

结合上面的知识再看一下 Google的例子 ,可能体会的更加深刻。

首先看实现的效果:

Picture

如果让大家自己来实现这个效果的话,相信很多童鞋会采用相对布局,将send按钮位于屏幕最下方,然后上面的三个EditText从上往下依次排列。但是message的EditText要铺满剩余的空间,这个怎么实现? 有的童鞋会不屑的说了,这有什么难的,把message的高度设置match_parent并且位于subject和send之间即可。代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp">

    <EditText
        android:id="@+id/et_to"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/to" />

    <EditText
        android:id="@+id/et_subject"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/et_to"
        android:hint="@string/subject" />

    <EditText
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_above="@+id/btn_send"
        android:layout_below="@id/et_subject"
        android:gravity="top"
        android:hint="@string/message" />

    <Button
        android:id="@+id/btn_send"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_alignParentRight="true"
        android:layout_gravity="right"
        android:text="@string/send" />
</RelativeLayout>

但是如果采用本文讲解的weight可能会更加的简单。这个布局关键的一点是message要铺满subject与send之间的区域。问题是如何实现铺满呢? 对了! 本文讲解的 weight 的核心就是瓜分父布局剩余的空间。全部瓜分不就是铺满嘛! 那么代码也就出来了:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="16dp"
    android:paddingRight="16dp"
    android:orientation="vertical" >
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/to" />
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:hint="@string/subject" />
    <EditText
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:gravity="top"
        android:hint="@string/message" />
    <Button
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_gravity="right"
        android:text="@string/send" />
</LinearLayout>

着重看一下message的布局:


<EditText
       android:layout_width="match_parent"
       android:layout_height="0dp"
       android:layout_weight="1"
       android:gravity="top"
       android:hint="@string/message" />

没错,采用了极为巧妙的方法。其他的子布局都不设置 layout_weight, 也就是默认是0 。 那么message将获取全部的剩余空间,实现了铺满的效果。

后记

相信阅读到这里的童鞋们,对文章开头的问题应该已经知道答案了。如果还有童鞋不知道答案,可以试着将文章开头的两个Button的内容改一下,一个叫AAAAAAAAA,一个叫B。您再看一下效果,可能就明白了。至于那个也对也不对的问题,“不对”的原因是他们要瓜分的是 剩余 空间。本文止。

分享到:
我来说两句
facelist
您需要登录后才可以评论 登录 | 立即注册
所有评论(2)
enthus45 2018-1-17 23:32
沙发
回复
enthus45 2018-1-17 23:35
学习了
回复

站长推荐

通过邮件订阅最新安卓weekly信息
上一条 /4 下一条

下载安卓巴士客户端

全国最大的安卓开发者社区

广告投放| 下载客户端|申请友链|手机版|站点统计|安卓巴士 ( 粤ICP备15117877号 )

返回顶部