9

我想这应该是一个相当容易回答的问题,如果您比我更了解 XML 布局的话。在使用match_parent layout_height时,我似乎没有得到我所想的。

我有一个带有android:orientation="vertical"的LinearLayout根元素。在这个 LinearLayout 里面我想要三个元素: - TextView - ListView - TextView

对于这两个 TextView,我设置了android:layout_height="wrap_content"以便它们的高度仅与显示其内容所需的一样高。问题是,我希望一个 TextView 位于表单的顶部,另一个位于表单的底部,而 ListView 会填满表单上的任何可用空间。所以这是我的 xml 布局的样子:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:text="Top TextView" />

<ListView
    android:id="@+id/listView_Species"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:text="Bottom TextView" />

但它不起作用。这就是我得到的。我选择了 ListView 以便将其突出显示。注意它是如何一直延伸到表单底部的,将底部的 TextView 推离表单。 XML 布局 1

当我将 ListView 的 layout_height 属性更改为某个固定值时,例如 180dp,这就是表单的样子。我只是发布这个来证明底部的 TextView 在那里,但我仍然不知道如何将它固定到屏幕的底部,而 ListView 占用了剩余的任何空间,但在两个 TextView 之间。

XML 布局 2

提前致谢。

4

3 回答 3

20

虽然其他答案试图解决您的问题(他们实际上并没有 - 他们建议您做一些看起来相似但在不同设备上可能看起来不错或可能不好看的事情),但没有人填补您对 LinearLayouts 知识的空白和match_parent。而且这些差距非常普遍——谷歌的文档仍然远远低于一流水平。

首先,视图如何在 LinearLayout 中工作?为简单起见,让我们来看看绘制 LinearLayout 的过程orientation="vertical"

  1. 检查 LinearLayout 的第一个孩子的高度(简称 LL)。如果高度是match_parentfill_parent(同一事物的旧名称),则视图的高度将被拉伸以填充整个查看区域。如果高度为wrap_content,则测量视图占用的垂直空间并将该空间用于视图。如果高度是一个非零数字,则使用恰好相同的像素作为视图的高度(如果太小可能会裁剪)。如果高度为 0,请参见下文。
  2. 将下一个视图放在 1 中的视图下方。检查其高度并采取相应措施。
  3. 继续查看所有视图。如果视图被推离底部,继续并停止计算,因为没有人会看到它或任何后续视图(假设没有 ScrollView)。
  4. 如果 View 的高度为 0,请检查它的gravity. 这需要第二次通过,存储所有视图的重力,然后按比例分配它们的高度。如您所料,第二遍布局所花费的时间加倍,这对于简单的布局来说并不重要。

您的示例说明: LL 的第一个孩子(第一个 TextView)被测量并占用一定数量的像素。然后您的 ListView 占用所有剩余空间(通过match_parent)。然后你的第二个 TextView 根本没有绘制,因为它不在屏幕底部。这几乎是你观察到的,但现在你明白为什么了。

解决方案:使用RelativeLayout。在这种情况下完美运行。

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
        android:id="@+id/top_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:textSize="30sp"
        android:text="Top TextView" />

    <TextView
        android:id="@+id/bottom_tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:textSize="30sp"
        android:text="Bottom TextView" />

    <ListView
        android:id="@+id/listView_Species"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_below="@id/top_tv"
        android:layout_above="@id/bottom_tv"
        />
</RelativeLayout>

RelativeLayout 告诉布局充气器在顶部绘制第一个 TextView,然后在底部绘制第二个 TextView,然后用您的 ListView 填充其余空间。我相信这正是你想要的。

欢迎来到安卓。你会经常使用这种模式!

于 2016-09-14T00:09:26.223 回答
12

将高度更改ListView为 0dp 并添加weight=1
ie:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:text="Top TextView" />

<ListView
    android:id="@+id/listView_Species"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="1" />

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:textSize="30sp"
    android:text="Bottom TextView" />
于 2013-08-18T13:31:37.037 回答
3

使用 android:layout_weight 为最外层布局内的小部件定义权重。将它们的高度声明为0dp,然后定义android:layout_weight它们中的每一个。他们三个的总重量总和应该是1。根据您的需要,您可以0.1定义顶部和底部TextView的重量并定义0.8到ListView。

<TextView
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight = "0.1"
    android:textSize="30sp"
    android:text="Top TextView" />

<ListView
    android:id="@+id/listView_Species"
    android:layout_width="match_parent"
    android:layout_weight = "0.8"
    android:layout_height="0dp" />

<TextView
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:textSize="30sp"
    android:layout_weight = "0.1"
    android:text="Bottom TextView" />
于 2013-08-18T13:30:09.287 回答