Android: 如何测量ListView的总高度

23

我需要测量ListView的总高度,但是似乎我一直得到错误的值。我正在使用这段代码:

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

    int totalHeight = 0;
    int desiredWidth = MeasureSpec.makeMeasureSpec(listView.getWidth(),
            MeasureSpec.AT_MOST);
    Log.w("DESIRED WIDTH", String.valueOf(listAdapter.getCount()));
    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        listItem.measure(desiredWidth, MeasureSpec.UNSPECIFIED);
        totalHeight += listItem.getMeasuredHeight();
        Log.w("HEIGHT"+i, String.valueOf(totalHeight));
    }

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

问题在于我收到的高度比应该收到的高度要大。每个列表项的测量方式都不同,但所有项的高度都相同,因此绝对不应该这样做。每个元素的高度至少是其实际高度的两倍。
提前感谢您。
编辑1:
我有两个ListView,它们都有带有6-7个EditText字段的项目。如果用户想要编写/删除EditText中的值,则显示/隐藏ListView。除了当我想要显示列表时,它需要很多空间,因为方法计算出ListView需要很多空间之外,一切都运行良好。因此,在该ListView下面有很多空白空间。比所需空间多三倍。

1
https://dev59.com/s3E95IYBdhLWcg3wbtbO - RobinHood
谢谢,但对我没有用。我认为我有这个问题是因为我不只有一个ListView。可能存在一些空间覆盖的冲突。 - Cristiano
3个回答

53

终于做到了!这是可以测量ListView高度并将其设置为全尺寸的工作代码:

public static void getTotalHeightofListView(ListView listView) {

    ListAdapter mAdapter = listView.getAdapter();

    int totalHeight = 0;

    for (int i = 0; i < mAdapter.getCount(); i++) {
        View mView = mAdapter.getView(i, null, listView);

        mView.measure(
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),

                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));

        totalHeight += mView.getMeasuredHeight();
        Log.w("HEIGHT" + i, String.valueOf(totalHeight));

    }

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

}

7
您应该更改该方法的名称。以“get”开头意味着该方法会返回一个非void的值。 - Sky Kelsey
5
你还需要添加 listView.getPaddingTop()listView.getPaddingBottom() - njzk2
1
还假设您已经固定了listView条目的高度。上面的代码中,包含ViewGroup的宽度不可用,因为它无法处理变量高度/ layout_height="wrap_content" 条目。 - arober11
7
当单元格高度不同时,它无法正常工作。 - Sergei S
2
这个不起作用。 - IntoTheDeep
显示剩余4条评论

3

可以尝试类似以下的代码:

listItem.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

  public void onGlobalLayout() {
    int listItemHeight = listItem.getHeight();
  }
});

如果您想获取ListView的高度,请尝试以下方法:
listView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {

  public void onGlobalLayout() {
    int listViewHeight = listView.getHeight();
  }
});

您也可以查看这个链接:计算列表视图的大小或如何告诉它完全展开


谢谢,但对我不起作用。我在第一篇帖子中做了一个编辑。我认为问题在于多个列表。 - Cristiano
如果有一个包含相同高度项的列表,那么我想执行list.LayoutParams = new LinearLayout.LayoutParams(fill_parent, thisFixedHeight * Count)是正确的方法,无需进行任何迭代。真正的问题是如何处理包含列表的列表的列表。 - Léon Pelletier

0

ListView会缓存视图项并重复使用它们。如果您有一个包含1000个项但只有6个可见的列表视图,那么渲染剩下的994个是没有意义的。

测量整个ListView意味着要渲染每个ListItem,这似乎有点过度。

我不知道您想要实现什么,但可能有更好的方法:)


我没有那么多的项目 :) 我有两个ListView,它们都有6-7个EditText字段的项目。如果用户想要编写/删除EditText中的值,我会显示/隐藏ListView。除了当我想要显示列表时,它需要大量的空间,因为方法计算ListView需要大量的空间之外,一切都运行良好。因此,在该ListView下面有很多空白空间。比所需的空白空间多三倍。 - Cristiano
但是ListView不知道你将如何使用它,因此它是以这种方式编写的。如果你想让其中一个ListView消失并释放屏幕上的空间,以便其他列表填充,请使用View.setVisibility(View.GONE)。 - Thibault D.
我正在使用 View.setVisibility(View.GONE),但是当我再次显示它时,它占用了非常大的空间,整个屏幕都是空白。我正在查看@RobinHood发布的链接。看起来他们通过不同的测量方式成功地实现了这一点。 - Cristiano

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