Android 为什么 ListView 项目不会增长以包装其内容?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1661293/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 03:26:00  来源:igfitidea点击:

Why do ListView items not grow to wrap their content?

androidlistview

提问by Matthias

I have a rather complex ListView, with variable list item heights. Under certain conditions, I need to display an additional view in a list item, which is hidden by default (View.GONE). By enabling it (View.VISIBLE), the list item grows in height (or at least it's supposed to).

我有一个相当复杂的 ListView,具有可变的列表项高度。在某些情况下,我需要在列表项中显示一个额外的视图,默认情况下是隐藏的 (View.GONE)。通过启用它 (View.VISIBLE),列表项的高度会增加(或者至少应该增加)。

The problem: Even though I declare the item's root layout to wrap_content, and each component in the item to fill_parent, the view I hide/show which is supposed to change the item's height is simply cut off at the bottom instead of its parent (the item layout) growing in height to fully display it.

问题:即使我将项目的根布局声明为 wrap_content,并将项目中的每个组件都声明为 fill_parent,我隐藏/显示的应该更改项目高度的视图只是在底部而不是其父级(项目布局)高度增长以完全显示它。

Are there any gotchas related to ListViews and item layouts and item height which I may have missed?

是否有任何与我可能遗漏的 ListViews 和项目布局以及项目高度相关的问题?

Some more observations:

还有一些观察:

For testing purposes I have now reduced the list item layout to just contain the root LinearLayout and an ImageView. When I set the LinearLayout height to e.g. 200dip and the ImageView to fill_parent, I would have expected the ImageView to grow until it hits the 200dip limit set by its parent.

出于测试目的,我现在已将列表项布局缩减为仅包含根 LinearLayout 和一个 ImageView。当我将 LinearLayout 高度设置为例如 200dip 并将 ImageView 设置为 fill_parent 时,我会期望 ImageView 增长直到它达到其父级设置的 200dip 限制。

However, the image will instead be only ever as tall as its bitmap resource (as if I had set it to wrap_content) and the whole list item will be of the same height (i.e. as if I had set it to wrap_content, too).

但是,图像的高度只会与其位图资源一样高(就像我将其设置为 wrap_content 一样),并且整个列表项的高度将相同(即,就像我也将其设置为 wrap_content 一样)。

If however I set the image height to e.g. 200dip, then the list item will grow in height, and so will the item layout.

但是,如果我将图像高度设置为例如 200dip,则列表项的高度将增加,项目布局也将增加。

In other words, the layout_height of the list item layout is completely ignored, and so is any height value on ImageView other than a hard-coded pixel value.

换句话说,列表项布局的 layout_height 被完全忽略,ImageView 上除硬编码像素值之外的任何高度值也是如此。

采纳答案by Matthias

I managed to fix this, but I don't understand why.

我设法解决了这个问题,但我不明白为什么

As I mentioned, I had set the layout_heightof the list item layout to wrap_content(since fill_parentis meaningless here, considering that a ListView is indefinitely tall).

正如我所提到的,我已经将layout_height列表项布局的 设置为wrap_content(因为fill_parent这里没有意义,考虑到 ListView 是无限高的)。

However, I had set the layout_heightof all views insidethat layout to fill_parent. The problem disappeared when setting them to wrap_contentinstead.

但是,我已将该布局layout_height的所有视图的设置为。当将它们设置为时,问题就消失了。fill_parentwrap_content

This raises two other questions:

这引发了另外两个问题:

1) What are the semantics of a view asking to fill_parent, when the parent wraps_content? Which size request takes precedence?

1)fill_parent当父视图请求时视图的语义是什么wraps_content?哪个尺寸请求优先?

2) How would I ever make a view fill a list item if fill_parentapparently doesn't work?

2)如果fill_parent显然不起作用,我将如何让视图填充列表项?

Thanks for your input guys.

感谢您的投入。

回答by PeBek

Try this: http://www.java2s.com/Code/Android/UI/setListViewHeightBasedOnChildren.htm

试试这个:http: //www.java2s.com/Code/Android/UI/setListViewHeightBasedOnChildren.htm

public class Utils {

    public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter(); 
        if (listAdapter == null) {
            // pre-condition
            return;
        }

        int totalHeight = 0;
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
        listView.requestLayout();
    }     
}

回答by CommonsWare

How are you inflating your rows?

你如何膨胀你的行?

If you are not using it right now, try using LayoutInflater#inflate(layoutId, parent, false)(where parentis the AdapterViewsupplied to getView()or newView()):

如果你不使用它的权利,请尝试使用LayoutInflater#inflate(layoutId, parent, false)(这里parentAdapterView提供给getView()newView()):

v = getLayoutInflater().inflate(R.layout.list_item, parent, false);

回答by kirhgoff

The problems with layout could be caused by ScrollView to be the wrapper

布局问题可能是由 ScrollView 作为包装器引起的

I stumbled upon some note in http://developer.android.com/reference/android/widget/ExpandableListView.html

我在http://developer.android.com/reference/android/widget/ExpandableListView.html 中偶然发现了一些注释

"...Note: You cannot use the value wrap_content for the android:layout_height attribute of a ExpandableListView in XML if the parent's size is also not strictly specified (for example, if the parent were ScrollView you could not specify wrap_content since it also can be any length. However, you can use wrap_content if the ExpandableListView parent has a specific size, such as 100 pixels."

"...注意:如果未严格指定父级的大小,则不能在 XML 中为 ExpandableListView 的 android:layout_height 属性使用值 wrap_content(例如,如果父级是 ScrollView,则不能指定 wrap_content,因为它也可以可以是任意长度。但是,如果 ExpandableListView 父级具有特定大小,例如 100 像素,则可以使用 wrap_content。”

I removed wrapping ScrollView and linear layout started working properly. Now its only to understand how to wrap the stuff to ScrollView. God help me

我删除了包装 ScrollView 并且线性布局开始正常工作。现在它只是了解如何将内容包装到 ScrollView。神救救我

But anyway this is really weird behavior. I think that fill_parent is not really correct wording. When using heirarchyviewer tool I always see WRAP_CONTENT and MATCH_PARENT values for layout_width and leayout_height. So probably fill_parent is actually means match_parent which puts me in cognitive dissonance.

但无论如何,这真的是很奇怪的行为。我认为 fill_parent 并不是真正正确的措辞。使用 heirarchyviewer 工具时,我总是看到 layout_width 和 leayout_height 的 WRAP_CONTENT 和 MATCH_PARENT 值。所以可能 fill_parent 实际上意味着 match_parent 这让我陷入认知失调。

回答by roys

I use the "AbsListView.LayoutParams" to configure the width and height manually inside "Adapter.getView()".

我使用“AbsListView.LayoutParams”在“Adapter.getView()”中手动配置宽度和高度。

回答by Dandre Allison

If you're using a custom Viewin as the list item that is resizing, then you can take from PeBek's answer and do this when you construct the View

如果您使用自定义Viewin 作为调整大小的列表项,那么您可以从 PeBek 的答案中获取并在构建View

addOnLayoutChangeListener(
            new OnLayoutChangeListener() {
                @Override
                public void onLayoutChange(View _, int __, int ___, int ____, int bottom, int _____, int ______,
                                           int _______, int old_bottom) {
                    final ListView list_view = (ListView) getParent();
                    final ViewGroup.LayoutParams params = list_view.getLayoutParams();
                    params.height += bottom - old_bottom;
                    list_view.setLayoutParams(params);
                    list_view.requestLayout();
                }
            });

When the Viewgets resized this callback method will me run and it updates the ListViewheight to include the change in height (delta bottom). The other values, if they prove useful for you are view(reference to the view), left, top, right, bottom, old_left, old_top, old_right, old_bottom. It works for expanding and collapsing the view.

View调整大小时,此回调方法将运行并更新ListView高度以包括高度的变化(底部增量)。其他值(如果证明对您有用)是view(参考视图)、lefttoprightbottomold_leftold_topold_rightold_bottom。它适用于展开和折叠视图。

API 11is required for OnLayoutChangeListener, don't know if there's a backward compatible way to do so.

需要API 11OnLayoutChangeListener,不知道是否有向后兼容的方法。

回答by Fra

I had the same problem: i would like to have a list inside my activity that fill all the screen either when the device is in vertical than in horizontal orientation. I solve the problem using al Linear Layout that have height that have to fill_parent, and setting the height of the item in the list to 0dp while the layout_weight is setter to 1.

我有同样的问题:我想在我的活动中有一个列表,当设备处于垂直方向而不是水平方向时,它会填满所有屏幕。我使用高度必须为fill_parent的所有线性布局解决了这个问题,并将列表中项目的高度设置为0dp,而layout_weight设置为1。

android:layout_weight="1"
android:layout_height="0dp"

回答by Nouman Ch

this works for me

这对我有用

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"

    android:padding="@dimen/activity_vertical_margin">

    <TextView
        android:id="@+id/tv_status"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:textSize="17sp"
        android:text="@string/text_list_devices" />

    <ListView
        android:id="@+id/lv_paired"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        android:cacheColorHint="#00000000"
        android:layout_above="@+id/signup_t"
        android:layout_below="@id/tv_status"
        />

    <Button

        android:id="@+id/signup_t"
        style="?android:textAppearanceSmall"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:textColor="@android:color/white"
        android:layout_alignParentBottom="true"
        android:text="Print All Records"
        android:typeface="sans"
        android:layout_marginLeft="45dp"
        android:layout_marginRight="45dp"
        android:textSize="24sp"
        android:background="@drawable/selector_for_button"
        android:textStyle="bold" />
</RelativeLayout>

回答by Budhdi Sharma

Things to note about column alignment:

列对齐的注意事项:

  • The container LinearLayout element uses horizontal orientation and android:layout_width as match_parent.
  • The TextView elements use android:layout_width="0dp"
  • Each of the two TextView elements uses android:layout_weight="1" so that they use equal amounts of the available width.
  • The android:layout_width property of each TextView element is set to "0dp".
  • 容器 LinearLayout 元素使用水平方向和 android:layout_width 作为 match_parent。
  • TextView 元素使用 android:layout_width="0dp"
  • 两个 TextView 元素中的每一个都使用 android:layout_weight="1" 以便它们使用等量的可用宽度。
  • 每个 TextView 元素的 android:layout_width 属性都设置为“0dp”。