如何在GridLayout中限制ListView的高度?

5
我有一个包含ListViewTextViewGridLayout。当向ListView添加项目时,它会增长并将下方的TextView推出屏幕。我认为在ListView上设置layout_gravity="fill"可以使其不增长,而是占用所有可用空间。

如何配置ListView以使用可用空间而不是增长并将视图推到屏幕下方?

我正在寻找使用GridLayout的解决方案。我知道在我的情况下,也可以使用LinearLayout。但是这只是一个最小化的测试用例来说明我的问题。

如果可能,我不想以编程方式设置高度。

<android.support.v7.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:columnCount="1"
    app:useDefaultMargins="true" >

    <ListView
        app:layout_gravity="fill" />

    <TextView
        android:text="TextView" />

</android.support.v7.widget.GridLayout>

只是为了我理解你的问题,你想让你的ListView具有静态高度并且可以单独滚动?也就是说,当你在ListView内滚动时,GridView的其余部分不会滚动。 - varsha-venkatesh
是的,ListView 应该占用所有可用的空间。它也应该是可滚动的,但 GridView 不应该滚动,而在 ListView 下面的 TextView 应该始终可见。 - Micha Wiedenmann
你不能直接使用GridLayout来实现你想要的效果。即使文档中也指出该小部件不支持权重概念,并建议将子项包装在LinearLayout中。 - user
这里:_"GridLayout不支持权重原则。因此,通常无法配置它来在多个组件之间分配多余的空间。 然而,某些常见用例可以按如下方式进行调整。要在单元格组中在组件周围放置相等数量的空间,请使用CENTER对齐(或gravity)。要完全控制行或列中多余空间的分布,请使用LinearLayout子视图来容纳相关单元格组中的组件..."_ - Onik
1
因为 ListView 的高度不是固定的,而是随着新内容的添加而扩展,所以除非您使用具有权重的 LinearLayoutRelativeLayout 作为 ListViewTextView 的包装器,否则无法通过 XML 属性实现所需的行为。 - Onik
显示剩余2条评论
4个回答

7
这个回答是对问题的评论的扩展,试图解释为什么不能通过XML和GridLayout的属性来实现。将GridLayout添加到框架中可以解决许多关于嵌套布局的缺点之一,其中之一是无法同时控制水平和垂直轴上的对齐,正如Philip Milne在文章New Layout Widgets: Space and GridLayout中所描述的那样。
这种对齐控制是通过layout_gravity参数执行的,其描述说明该参数"指定组件应如何放置""在其单元格组中"而不是在根布局内)。基本上,它与LinearLayout相同,这也在文章中提到:"对齐/重力也像LinearLayout中的重力一样工作..."我们知道,对于LinearLayouts,一旦视图占据了屏幕的整个高度(例如您的ListView),如果将布局方向设置为"垂直",则其下面的视图会超出屏幕。
如果我们查看GridLayout.LayoutParams文档,我们不会找到任何参数,允许单元格组内的组件粘贴在父布局的特定位置,并独立于同一组中其他组件的大小保持在该位置; 类似于RelativeLayout的layout_align[...]参数。
我最好的猜测是,在GridLayout中缺少此类参数是为了更好地对齐控制比嵌套布局更好。
我相信您知道除GridLayout属性之外使用其他方法解决问题的解决方案。 我只是建议一种方法,使答案看起来已经完成:
<GridLayout
    ... >

    <RelativeLayout
       ... >

        <TextView
            ...
            android:id="@+id/tv"
            android:layout_alignParentBottom="true" />

        <ListView
            ...
            android:layout_above="@id/tv">
         </ListView>

    </RelativeLayout>

</GridLayout>

1
您可以通过编程设置ListView的高度,具体方法如下:
ListView listView = (ListView) findViewById(R.id.listview);
LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) listView.getLayoutParams();
layoutParams.height = listHeight;
listView.setLayoutParams(layoutParams);
listView.setAdapter(listAdapter);

然而,我无法想出一种适用于多个设备的扩展方式。


0
如果您愿意,您可以将 TextView 放在页脚中,这样 ListView 就不会将其推开。虽然我不确定这是否是您想要的。
<?xml version="1.0" encoding="utf-8"?>
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent" >

<!-- Footer aligned to bottom -->

<RelativeLayout
    android:id="@+id/footer"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignParentBottom="true"
    android:background="@drawable/background"
    android:gravity="center" >

    <!-- TextView Here -->

</RelativeLayout>

<!-- Content below header and above footer -->

<RelativeLayout
    android:id="@+id/content"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_above="@id/footer"
    android:gravity="center" >

    <!-- ListView Here -->

</RelativeLayout>
</GridLayout>

0

如果你想限制ListView的高度,而又使用了wrap content属性,那么唯一的方法就是继承该类,重写onMeasure方法,并在其中设置高度的限制。我不知道有哪些XML参数可以达到你想要的效果。


ListView 如何/在哪里设置为“wrap_content”? - Micha Wiedenmann
你说得对,它并没有使用GridLayout的子元素进行定义,但从你的描述来看,它的行为就像是使用了GridLayout(我自己还没有尝试过)。但我的建议仍然有效。GridView会将可用空间的大小发送到onMeasure方法中。如果你使用这些值与setMeasuredDimensions一起使用,你应该会受到可用空间的限制。 - snapix
就像Onik在他的评论中所说的那样,但如果你想避免包装器布局,你可以使用我的建议。你原则上理解了吗?还是我需要给你提供一些代码? - snapix
我正在寻找一个XML解决方案,或者一个解释为什么不能仅使用XML来完成此操作的说明。 - Micha Wiedenmann

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