ListView会将其他视图推出屏幕外

10

我正在努力让页面布局正确,我试图提供尽可能简短和小的示例来说明我的问题。

我的目标是在屏幕顶部和底部有一个标题和页脚视图,中间有一个列表视图,另外还有一个视图(我们称之为“标签”,它是屏幕截图中的灰色框)。当需要滚动ListView时,这个标签和页脚应该始终显示。

可视化结果

ListView不需要滚动时(这是正确的):

when the ListView doesn't need to scroll

ListView需要滚动时,页脚和灰色框会被推出屏幕(错误):

when the ListView needs to scroll

布局

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:orientation="vertical">
    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="header"
            android:padding="20dp"
            android:textSize="18sp"
            android:background="@color/red"/>
    <ListView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:id="@android:id/list" />
    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="this should be directly below the ListView, but not pushed off screen when the ListView needs to scroll"
            android:padding="5dp"
            android:background="@color/light_gray"
            android:textColor="@color/black"/>
    <!-- Used to push the footer to the bottom -->
    <View android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="1"/>
    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="footer"
            android:padding="20dp"
            android:textSize="18sp"
            android:background="@color/blue"/>
</LinearLayout>

测试活动

public class TestActivity extends ListActivity
{
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        ArrayList<String> items = new ArrayList<String>();
        items.add("one");
        items.add("two");
        items.add("three");
        items.add("four");
        items.add("five");
        items.add("six");
        items.add("seven");
        items.add("eight");
        items.add("nine");
        items.add("ten");
        setListAdapter(new ArrayAdapter<String>(this, R.layout.simple_list_item_1, items));
        setContentView(com.myproject.android.R.layout.test);
    }
}

我尝试了几种不同的方法,比如给 ListView 添加 layout_weight="1" 并删除用于将页脚推到底部的空白 View。这基本上是我想要的,当 ListView 滚动时,它保持页脚和标签可见,但当仅有 1 或 2 个项目时,我需要在 ListView 正下方显示灰色框。我还尝试过使用 RelativeLayout,但没有成功。我想我完全误解了一些东西。

编辑

这是我使用 RelativeLayout 的尝试,但仍然不正确。
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent">
    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="header"
            android:padding="20dp"
            android:textSize="18sp"
            android:background="@color/red"
            android:id="@+id/header"
            />
    <ListView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:id="@android:id/list"
              android:layout_below="@id/header"/>
    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="this should be directly below the ListView, but not pushed off screen when the ListView needs to scroll"
            android:padding="5dp"
            android:background="@color/light_gray"
            android:textColor="@color/black"
            android:layout_below="@android:id/list"/>

    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="footer"
            android:padding="20dp"
            android:textSize="18sp"
            android:background="@color/blue"
            android:layout_alignParentBottom="true"
            android:id="@+id/footer"/>
</RelativeLayout>

相对布局(仍然错误):

相对布局尝试


为什么不直接使用RelativeLayout呢? - Renaud Favier
将ListView定位在页脚上方和页眉下方,这样它就不会重叠到它们的区域。 - Jeroen
你并不需要一个示例,http://developer.android.com/reference/android/widget/RelativeLayout.html已经足够了。使用android:layout_below,以及layout_alignParentTop/bottom。 - Renaud Favier
是的,如果我继承自ListActivity,我确实需要android:id/list。另外,告诉页脚在灰色视图下方不会改变任何东西。如果您有一个可行的示例,请发布它。否则,这完全没有帮助。无论如何,还是谢谢。 - wsanville
好的,我想我明白了,您希望在列表过长时,灰色部分能够覆盖页脚?我认为在您的情况下,您需要根据列表中的位置,在Java代码中更改布局属性,但是为什么您需要一个ListActivity呢?您可以不使用它来实现您想要的效果。 - Renaud Favier
显示剩余4条评论
5个回答

10
android:layout_weight="1"添加到ListView中。这将使其成为LinearLayout中最大的元素,而不会将其他元素推出屏幕。

2
那差不多就是我想要的,我在问题中提到过我尝试过这个,虽然对于ListView滚动的情况它是正确的,但是当它不滚动时,我真正想要的是直接位于ListView下方的灰色框。 - wsanville
哦,等一下,你难道不想要页脚吗? - dmon
请看问题中的第一张截图。当 ListView 不需要滚动时,那就是我想要的外观。如果我给它 layout_weight="1" ,那么它就会被推下去,这不是我想要的。但是我确实想要一个页脚。 - wsanville
1
ListView提供了一种指定页脚视图的方法,请查看文档。唯一的注意事项是它们的行为有些滑稽。您需要添加页脚视图,然后再设置适配器。 - dmon

7
这种布局将头部放置在屏幕顶部,页脚放置在底部,列表填充屏幕其余部分。采用这种方法,列表元素永远不会被页脚遮挡。请查看如何在XML下方添加灰色框。
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent">
<TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="header"
        android:padding="20dp"
        android:textSize="18sp"
        android:background="@color/red"
        android:id="@+id/header"
        />
<TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="footer"
        android:padding="20dp"
        android:textSize="18sp"
        android:background="@color/blue"
        android:layout_alignParentBottom="true"
        android:id="@+id/footer"/>
<ListView android:layout_width="fill_parent"
          android:layout_height="fill_parent"
          android:id="@android:id/list"
          android:layout_below="@id/header"
          android:layout_above="@id/footer"/>


</RelativeLayout>

好的,这个XML解决了缺失页脚的问题。现在我们需要在列表末尾添加一个灰色的框。我认为有两种方法可以实现:


这很有帮助,我不知道addFooter方法。但我认为当ListView需要滚动时,无法使视图保持“粘性”(始终显示),这就是我想要的。 - wsanville
谢谢,经过长时间的思考,这是对我有效的解决方案。addFooterView() 的问题在于,如果列表很长,直到用户滚动到底部,页脚才会被隐藏。我更喜欢这个解决方案。 - RightHandedMonkey

2

我遇到的解决方案是在列表视图底部添加正向填充,同时在“页脚”顶部添加负向填充。这适用于线性布局或相对布局。

<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:paddingBottom="50dp"/>

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="-50dp"/>

1
两年晚回答这个问题,但我会留下我的解决方案,以便帮助有相同问题的人。我使用了2个嵌套的LinearLayouts和layout_weight来解决这个问题。可能不是最好的性能布局,但它达到了期望的效果。
您需要按照以下方式排列您的布局:
  1. 当ListView不占满整个屏幕时,它的高度将设置为wrap_content,以仅占用所需的空间。
  2. 你的ListView将位于一个高度使用layout_weight的布局中,因此当ListView未填充整个屏幕时,列表将仅占用所需的空间,并且当其大小足够大以将视图推出屏幕时,仅占用有限的屏幕空间。
  3. 灰色框视图应该紧接在步骤2的布局下方,其高度为wrap_content,且为步骤2的布局的兄弟节点。
  4. 此布局和灰色框将位于第二个具有wrap_content高度的布局中,以便它们可以一起保持。
  5. 现在你有一个包含列表和灰色视图的布局,如果列表过大,它不会将其他视图推出屏幕。你只需要将页脚视图移动到屏幕底部。

    5a. 如果作为根布局使用RelativeLayout,则可以像sgallego所说的那样使用android:layout_alignParentBottom。

    5b. 但是,如果使用的是LinearLayout,则需要创建第三个具有layout_weigth的布局,放置在步骤4的布局内,还需要添加一个空的视图,也具有layout_weigth,以填充空白的空间。

这里是一个有注释的示例。

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <!-- Header -->
    <TextView
        android:id="@+id/RecordStudy_StudyLabel"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/RecordStudy_StudyLabel"
        android:textSize="@dimen/text_large" />

    <!-- Body -->
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical" >

        <!--
        This layout encapsules the list and the button that must be immediately
        below the list with a wrap_content height, so the list plus the button
        fills only as much space as they need (if the list is not big enouth to
        fill the entire screen).
        -->
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical" >

            <!--
            Layout with varaible size with a list inside.
            Using layout_weight tells android that this layout should not grow
            greater then the screen, but uses only the free space. 
             -->
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1"
                android:orientation="vertical" >

                <!--
                Inside this limited height layout, there is a list with height
                wrap_content so it can grow as much as it needs INSIDE the
                layout (through scrolling).
                -->
                <ListView
                    android:id="@+id/RecordStudy_StudyList"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content" />

            </LinearLayout>

            <!-- Button immediately below the list -->
            <Button
                android:id="@+id/RecordStudy_AddStudy"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/RecordStudy_AddStudy" />

        </LinearLayout>

        <!-- Space between the list and the footer -->
        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="1" />

    </LinearLayout>

    <!-- Footer -->
    <Button
        android:id="@+id/RecordStudy_ConfirmButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/RecordStudy_ConfirmButton" />

</LinearLayout>

0

我实施并发现有用的一种解决方案是将列表视图放在一个具有固定高度的线性布局中,这样它就不会扩展并与其他项目重叠。

就像这样:

<TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="header"
            android:padding="20dp"
            android:textSize="18sp"
            android:background="@color/red"
            android:id="@+id/header"
            />

<LinearLayout
    android:layout_width="fill_parent"
    android:layout_height="150dip" //assume 150dip height is sufficient

    <ListView android:layout_width="fill_parent"
              android:layout_height="wrap_content"
              android:id="@android:id/list"
              android:layout_below="@id/header"/>
</LinearLayout>

    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="this should be directly below the ListView, but not pushed off screen when the ListView needs to scroll"
            android:padding="5dp"
            android:background="@color/light_gray"
            android:textColor="@color/black"
            android:layout_below="@android:id/list"/>

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