如何使FrameLayout填满其父元素的高度,以便整个页面一起滚动?

6
我有一个FrameLayout,通过在TabWidget上点击选项卡来加载Fragment。我无法弄清楚如何使FrameLayout的高度与其内容一样高,以便整个包含ScrollView作为一个单独的滚动视图滚动,而不是分开的滚动视图。
这是此Fragment结构的可视示例:
正如您所看到的,Frame Layout Visible Height只显示一个碎片行,实际上有几个碎片行。我现在可以在FrameLayout中滚动以查看其他行,但这不是我想要的。 FrameLayout由LinearLayout组成,其中包含一个GridView,它们的layout_height设置为wrap_content。
我尝试将FrameLayout的高度硬编码为500dp,效果很好,除了它不再具有动态大小。每次将新图像加载到内部内容中,我需要在程序中重新调整FrameLayout的大小吗?是否有布局属性可设置以将其高度拉伸到匹配其内部内容?
这是我的布局xml文件:
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<LinearLayout
    android:orientation="vertical"

    android:layout_width="fill_parent"
    android:layout_height="wrap_content">
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="200dp">
        <!-- CONTAINS USER INFO AND STATS -->
    </RelativeLayout>
    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
        <LinearLayout
            android:orientation="vertical"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:background="#ffffff">
            <TabWidget
                android:id="@android:id/tabs"
                android:layout_width="fill_parent"
                android:layout_height="60dp"
                android:weightSum="2">
            </TabWidget>
            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                >
            </FrameLayout>
        </LinearLayout>
    </android.support.v4.app.FragmentTabHost>
</LinearLayout>
</ScrollView>

谢谢!


由于我要在这上面设置赏金,所以我想分享一下我到目前为止已经弄清楚的内容。

在缩略图中,当每个图像加载时,我会调用GridLayout中保存图像的函数来计算图像数量并设置GridLayout的高度。虽然这样做似乎有点低效,但它运行良好。

我所做的是设置GridLayout的高度,然后在其父级上调用requestLayoutinvalidate。这种方法可行,但仅限于在图片加载时切换到不同的标签页并返回到缩略图时才能正常工作。这让我认为我没有在正确的时间或对象上进行更新。

无论如何,话说回来。有人知道如何使GridLayout的高度扩展以容纳其内容(而不是滚动),以便我可以滚动整个页面(包括顶部部分)吗?


我还应该添加GridView布局:

<GridView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/grid"
android:stretchMode="columnWidth"
android:gravity="center"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:drawSelectorOnTop="false"
android:fastScrollAlwaysVisible="false"
android:fastScrollEnabled="false"
android:numColumns="3"
android:choiceMode="none">
</GridView>

我喜欢你描述问题的方式(我的意思是图片),做得很好! - pskink
请重新考虑布局:它不符合 Android 的设计规范!例如,选项卡应该保持在顶部。 - brescia123
你在跟 @brescia123 唱反调!我只是在按照给我的设计来匹配。 - Keith
虽然你声称正在使用 GridLayout,但是你关于内部滚动的评论和发布的 XML 显示,实际上你正在使用 GridView,它是一个独立的滚动容器。GridLayout 不会有这个问题,但另一方面它无法动态解决列宽。 - corsair992
https://dev59.com/s3E95IYBdhLWcg3wbtbO 提供了一些解决方案,可以使 ListView 充满整个屏幕。对于 GridView 来说应该是类似的,因为唯一的区别就是每行有多个项目。或者,使用实际的 GridLayout,这些不是可扩展的窗口,并在代码中填充内容。 - zapl
显示剩余3条评论
3个回答

4

我曾遇到类似的情况,但是我的控件是ListView而不是GridView。你说得对,每次添加一个item或调用notifyDataSetChanged()时都需要动态设置高度。

以下代码适用于每行高度不同的ListView:

private void setListViewHeightBasedOnChildren(MyQueueAdapter listAdapter) {

    int desiredWidth = MeasureSpec.makeMeasureSpec(
            mListView.getWidth(), MeasureSpec.AT_MOST);
    int totalHeight = 0;

    View view = null;
    int i;
    for (i = 0; i < listAdapter.getCount(); i++) {
        view = listAdapter.getView(i, view, mListView);

        view.measure(desiredWidth, MeasureSpec.UNSPECIFIED);

        totalHeight += view.getMeasuredHeight();
    }

    ViewGroup.LayoutParams params = mListView.getLayoutParams();
    params.height = heightList
            + (mListView.getDividerHeight() * (listAdapter
                    .getCount() + 3));

    heightListComplete = params.height;
    mListView.setLayoutParams(params);

}

您需要根据自己的需求修改此代码,在您的情况下,不需要循环,因为每行的高度是静态的。如果您需要更多帮助,请告诉我。

备选方案

如果您知道视图的高度(以dp为单位),则可以轻松将dp转换为px,并根据行数设置gridview的高度。


请记住,这将强制立即解析整个布局(包括所有行),并同时将所有图像存储在内存中,而不是执行GridView本来会执行的行的延迟回收。避免这种情况的一种方法是使用GridView自己的滚动,通过将顶部布局添加为其标题,但这将要求所有选项卡都包含一个GridView布局(每个都在GridView上设置自己的ListAdapter)。可能还有其他可能的解决方案,但它们实施起来会更加复杂。 - corsair992
是的,这就是为什么我说他不需要循环。只需要一个视图的高度就足够了,如果他已经知道了行的高度(以dp为单位),他可以轻松地将其转换为px并设置gridview的高度。 - Naveen
你似乎没有理解我的评论。请查看你从中获取的答案(并且应该在你的答案中进行归属的答案上的评论和被接受的答案)。 - corsair992
非常感谢你,Naveen!我一直在使用rootView.height=来更改高度,而不是使用layoutParams。终于解决了。 - Keith

2
使用动态尺寸时,如果在wrap_content中嵌套match_parent,就会出现问题。一个尝试获取其内容的最小值,而另一个则试图将自己变得与其父级一样大。最终两边都无法正确缩放。 ScrollView属于此类,它是可扩展窗口到其内容,因此不能是wrap_content,而内容也不能是match_parent,因为其父级是虚拟无限空间。
要解决内容大小问题:
- 将您的ScrollView的根布局(在此处为LinearLayout)设置为固定大小,这样其内容可以再次设置为match_parent。 - 一直使用wrap_content。 - 将两个方法结合起来:先使用wrap_content,直到一个子元素定义了绝对大小,然后在其中使用match_parentwrap_content的路线仅在布局中的所有元素从内部到外部都根据其内容正确扩展时才有效。除非添加某些内容,否则没有任何东西可以依赖于父级边界。
您的内容看起来相当动态。因此,您可能需要使用一些代码手动根据内容设置大小。例如,如果选项卡框架中的这些图像是GridView(本质上是再次具有网格内容的ScrollView),则需要手动设置其大小。在包含多个自由度的动态尺寸容器中有超过1个解决方法是无法自动完成的。

-1

您的框架布局的父级是一个高度为wrap_content的线性布局。同时,您的框架布局的高度也是wrap_content。请将它们都改为fill_parent。现在使用match_parent比fill_parent更受欢迎。


谢谢Hirak。不幸的是,那并没有改变任何事情。你有其他的想法吗? - Keith
检查每个父级。线性布局的父级相对布局为200dp。当您将线性布局的高度设置为match_parent时,实际上是200dp。 - Hirak Chhatbar
再次感谢Hirak,我尝试将每个父级设置为match_parent,但没有起作用。我的目标是在从互联网异步下载新项目添加到FrameLayout视图时自动更改FrameLayout的高度。然而,它似乎只设置为单个项目的高度,而不是完全加载的更高的高度。我需要告诉它在下载每个项目时重新测量吗? - Keith
啊,我明白你的意思了。基本上,如果我将FrameLayout设置为500dp,它会一起滚动(与其上面的RelativeLayout一起),这正是我想要的,因为FrameLayout将加载图像,可能有数百个,而顶部的RelativeLayout占用了太多空间,所以我希望它能随着它一起滚动。 - Keith
我很高兴能够帮到您。如果您觉得我的回答有帮助,请点赞:D - Hirak Chhatbar
显示剩余5条评论

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