Android中的线性布局和权重

288

我一直在Android文档中读到这个有趣的权重值。现在我想第一次尝试它,但它根本不起作用。

从文档中我理解,这个布局:

  <LinearLayout
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal">

     <Button
        android:text="Register"
        android:id="@+id/register"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dip"
        weight="1" />

     <Button
        android:text="Not this time"
        android:id="@+id/cancel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:padding="10dip"
        weight="1" />

  </LinearLayout>

需要创建两个水平对齐且共享空间的按钮。问题在于这两个按钮不会增长以填充空间。

我希望这些按钮可以增长并填充整行。如果两个按钮都设置为匹配父元素,那么只会显示第一个按钮并填充整行。


更新:Android百分比支持库也可以很好地实现这一点。http://code2concept.blogspot.in/2015/08/android-percent-support-lib-sample.html - Nitesh Tiwari
19个回答

750

记住以下三点:

  • 将子元素的android:layout_width属性设置为"0dp"
  • 设置父元素的android:weightSum属性(编辑: 此属性是可选的,因为默认情况下它已设置为子元素的layout_weight值之和)
  • 按比例设置每个子元素的android:layout_weight属性(例如:weightSum="5", 三个子元素分别为: layout_weight="1", layout_weight="3", layout_weight="1")

示例:

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:weightSum="5">

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

    <Button
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="3"
        android:text="2" />

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

</LinearLayout>

结果如下图所示:

Layout weight example


71
谢谢您提供设置宽度为零的提示。我还发现在父布局上设置weightSum是不必要的。 - Jason Moore
30
知道了,谢谢。如果你不想让子视图填充父视图的100%,设置weightSum仍然是有用的。 - Anke
13
对于静态的XML布局是正确的。如果你想在运行时动态地添加视图,你需要使用addView并使用布局参数,比如addView(button, new LinearLayout.LayoutParams(0, height, 1));即使你使用正确的宽度和权重值来膨胀布局,这也是正确的做法。 - Nuthatch
@Nuthatch,我不明白你的意思。特别是你说,“即使您使用正确的宽度和权重值膨胀布局,这也是正确的。”你能否请澄清一下? - batbrat
1
@batbrat是正确的,我正在动态生成UI。有时我将XML片段视为模板,然后在运行时修改或填充。这个技巧在这种情况下对我不起作用,我必须重新设置显式宽度和权重才能使其正常工作。 - Nuthatch
显示剩余9条评论

171

您没有设置layout_weight属性。您的代码中是 weight="1",应改为 android:layout_weight="1"


55

这是android:layout_weight。Weight只能在LinearLayout中使用。如果线性布局的方向是垂直的,则使用android:layout_height="0dp",如果方向是水平的,则使用android:layout_width="0dp"。它会完美地工作。


29

19

尝试将两个按钮的layout_width都设置为“0dip”,并将两个按钮的weight都设置为0.5


现在屏幕上两个按钮都消失了。 - Janusz
好的,然后将两个布局的宽度都设置为fill_parent,并将权重(weight)设置为0.5。 - jqpubliq
请查看这个这个。我有点困惑为什么这仍然不起作用,但也许这会给你一些想法。 - jqpubliq

7

就像@Manoj Seelan的答案所述:

android:weight替换android:layout_weight

当您在LinearLayout中使用Weight时,必须在LinearLayout中添加weightSum,并根据LinearLayout的方向将所有LinearLayout的子视图的宽度/高度设置为0dp

例如:

如果Linearlayout的方向是Vertical,则将所有LinearLayout的子视图的宽度设置为0dp

 <LinearLayout
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical"
     android:weightSum="3">

     <Button
        android:text="Register"
        android:id="@+id/register"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="10dip"
        android:layout_weight="2" />

     <Button
        android:text="Not this time"
        android:id="@+id/cancel"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:padding="10dip"
        android:layout_weight="1" />

  </LinearLayout>

如果Linearlayout的方向是水平的,则将所有LinearLayout子视图的高度设置为0dp
 <LinearLayout
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
     android:orientation="horizontal"
     android:weightSum="3">

     <Button
        android:text="Register"
        android:id="@+id/register"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:padding="10dip"
        android:layout_weight="2" />

     <Button
        android:text="Not this time"
        android:id="@+id/cancel"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:padding="10dip"
        android:layout_weight="1" />

  </LinearLayout>

7
在按钮的宽度字段中,将 wrap-content 替换为 0dp
使用视图的 layout_weight 属性。
android:layout_width="0dp"  

这是你的代码将会呈现的样子:
<LinearLayout
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
 android:orientation="horizontal">

 <Button
    android:text="Register"
    android:id="@+id/register"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:padding="10dip"
    android:layout_weight="1" />

 <Button
    android:text="Not this time"
    android:id="@+id/cancel"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:padding="10dip"
    android:layout_weight="1" />    

</LinearLayout>

layout_weight被用来按比例分配剩余空间。在这种情况下,两个按钮的宽度被设为"0dp",因此剩余的空间会在它们之间按照1:1的比例分配,也就是说,剩余的空间会被平均分配给两个按钮视图。


7

LinearLayout支持为每个子视图分配权重。此属性将一个“重要性”值分配给一个视图,并允许它扩展以填充父视图中的任何剩余空间。默认权重为零。

计算公式用于在子项之间分配任何剩余/额外空间,而不是总空间。

分配给子项的空间=(子项的个体权重)/(线性布局中每个子项权重的总和)

示例(1): 如果有三个文本框,其中两个声明了权重为1,而第三个没有权重(0),则剩余/额外空间分配给

1st text box = 1/(1+1+0) 
2nd text box = 1/(1+1+0) 
3rd text box = 0/(1+1+0) 

示例 (2):假设我们在水平行中有一个文本标签和两个文本编辑元素。 标签没有指定布局权重,因此它占用渲染所需的最小空间。 如果每个文本编辑元素的布局权重设置为1,则父布局中的剩余宽度将平均分配给它们(因为我们声称它们同等重要)。

calculation : 
1st label = 0/(0+1+1) 
2nd text box = 1/(0+1+1) 
3rd text box = 1/(0+1+1)

如果第一个文本框的layout_weight为1,第二个文本框的layout_weight为2,则剩余空间的三分之一将分配给第一个文本框,剩余的三分之二将分配给第二个文本框(因为我们声称第二个更重要)。
calculation : 
1st label = 0/(0+1+2) 
2nd text box = 1/(0+1+2) 
3rd text box = 2/(0+1+2) 

5
也许将这两个按钮的layout_width属性都设置为"fill_parent"可以解决问题。我刚在模拟器中测试了这段代码,它可以正常运行:
<LinearLayout android:layout_width="fill_parent"
          android:layout_height="wrap_content">

    <Button android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="hello world"/>

    <Button android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="goodbye world"/>

</LinearLayout>

请确保两个按钮的 layout_width 属性都设置为 "fill_parent"。

1
这只会将右侧按钮推出屏幕并仅显示第一个按钮。 - Janusz

4
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/logonFormButtons"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:baselineAligned="true"       
        android:orientation="horizontal">

        <Button
            android:id="@+id/logonFormBTLogon"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"            
            android:text="@string/logon"
            android:layout_weight="0.5" />

        <Button
            android:id="@+id/logonFormBTCancel"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"            
            android:text="@string/cancel"
            android:layout_weight="0.5" />
    </LinearLayout>

现在我更倾向于建议使用layout_weight ="50"和layout_width ="0px"。 - Yar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接