你真的了解weight和weightSum吗?

libingxue 8年前
   <p>看到本文的标题,很多童鞋会一脸不屑的说,这有什么不了解的。不就是通过weight来给子布局按比例来分配空间嘛!好,这个答案也对也不对。 此时有人会疑惑了,为什么也对也不对? 我先来举两个最常见的例子:</p>    <pre>  <code class="language-java"><?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></code></pre>    <pre>  <code class="language-java"><?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></code></pre>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/fd1a1ea64d6e382888d2baf23e8f1baa.png"></p>    <p style="text-align: center;">Paste_Image.png</p>    <p>这两个例子都能实现上图的效果。那么问题来了,这两个方式有什么区别吗? 眼尖的童鞋立马会说:当然有区别,一个 android:layout_width 是0, 另一个是 wrap_content。 那么这两个有什么区别吗? 为什么实现的效果是一样的? 我还要问一句,真的是一样吗?</p>    <p>如果对这个问题有所疑惑,那么兔子哥将带领大家来深入了解一下weight和weightSum,并通过阅读本篇文章,做到知其然,并且知其所以然。</p>    <h2><strong>什么是weight和weightSum</strong></h2>    <p>某位伟人曾经说过,要对某个知识点深入了解,最好的切入点就是仔细阅读知识点的定义。至于这位伟人是谁,什么?想不起来了?不用想了,就是这篇博文的作者,兔子哥大人也! ~~~好了,扯了这么多废话!我们还是先步入正题,先看看Google是怎么给 android:layout_weight 和 android:weightSum来定义的:</p>    <p><strong>Layout Weight</strong></p>    <p><a href="/misc/goto?guid=4959715417759002682" rel="nofollow,noindex">LinearLayout</a> also supports assigning a <em>weight</em> to individual children with the <a href="/misc/goto?guid=4959715417850745729" rel="nofollow,noindex">android:layout_weight</a> attribute. 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.</p>    <p>大体意思就是,android:layout_weight 这个属性代表了一个“重要性”的值,这个值的大小代表了该控件能在屏幕中占据多大的空间。这个值越大,表明该控件可以在父控件中占据较多的“ <strong>剩余</strong> ”空间。默认的weight是0。</p>    <p>在这里,大家一定要注意“ <strong>剩余</strong> ”两个字!大家往往容易忽略这一点,导致出现了很多问题。举个例子:水平方向布局的父类有三个子类,父类总的宽度是100,子类的宽度分别是10,20,30。 那么 android:layout_weight 这个属性的目的,就是瓜分剩余的 100 - 10 - 20 - 30,也就是剩余的40的使用权。没错! 就是android:layout_weight 这个属性 仅仅决定 哪个子类能瓜分到更多的40的部分!</p>    <p><strong>android:weightSum</strong></p>    <pre>  <code class="language-java">Defines the maximum weight sum. If unspecified, the sum is computed by adding the layout_weight of all of the children.</code></pre>    <p>这个就很好理解了,weightSum定义了weight 总和的最大值。如果 android:weightSum 没有定义,那么默认值就是通过各个子类的 layout_weight 累加得到。</p>    <h2><strong>工作原理</strong></h2>    <p>讲了这么多,举个例子来说明一下。</p>    <pre>  <code class="language-java"><?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></code></pre>    <p>效果如下图:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/9ad57896cc52dc30bfb287b3a46bb114.png"></p>    <p style="text-align: center;">Paste_Image.png</p>    <p><strong>内部的计算原理是:</strong></p>    <p>Button的宽度 = Button 的 width + Button的weight <strong>*</strong> 父布局(LinearLayout)的宽度 / weightSum</p>    <p>上面的例子,也就是 Button的宽度 = 0 + 0.5 <em>*</em> LinearLayout的宽度 / 1 = 0.5 * LinearLayout的宽度</p>    <p>也就是Button的宽度将占屏幕的一半。</p>    <h2><strong>Google官方例子</strong></h2>    <p>结合上面的知识再看一下 <a href="/misc/goto?guid=4959715417927319440" rel="nofollow,noindex">Google的例子</a> ,可能体会的更加深刻。</p>    <p>首先看实现的效果:</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/4408b9d195c693533e54985405d4c3e4.png"></p>    <p style="text-align: center;">Paste_Image.png</p>    <p>如果让大家自己来实现这个效果的话,相信很多童鞋会采用相对布局,将send按钮位于屏幕最下方,然后上面的三个EditText从上往下依次排列。但是message的EditText要铺满剩余的空间,这个怎么实现? 有的童鞋会不屑的说了,这有什么难的,把message的高度设置match_parent并且位于subject和send之间即可。代码如下:</p>    <pre>  <code class="language-java"><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></code></pre>    <p>但是如果采用本文讲解的weight可能会更加的简单。这个布局关键的一点是message要铺满subject与send之间的区域。问题是如何实现铺满呢? 对了! 本文讲解的 weight 的核心就是瓜分父布局剩余的空间。全部瓜分不就是铺满嘛! 那么代码也就出来了:</p>    <pre>  <code class="language-java"><?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></code></pre>    <p>着重看一下message的布局:</p>    <pre>  <code class="language-java"><EditText         android:layout_width="match_parent"         android:layout_height="0dp"         android:layout_weight="1"         android:gravity="top"         android:hint="@string/message" /></code></pre>    <p>没错,采用了极为巧妙的方法。其他的子布局都不设置 layout_weight, 也就是默认是0 。 那么message将获取全部的剩余空间,实现了铺满的效果。</p>    <h2><strong>后记</strong></h2>    <p>相信阅读到这里的童鞋们,对文章开头的问题应该已经知道答案了。如果还有童鞋不知道答案,可以试着将文章开头的两个Button的内容改一下,一个叫AAAAAAAAA,一个叫B。您再看一下效果,可能就明白了。至于那个也对也不对的问题,“不对”的原因是他们要瓜分的是 <strong>剩余</strong> 空间。本文止。</p>    <p> </p>    <p>来自:http://www.jianshu.com/p/9b0407252e8b</p>    <p> </p>