18

当列表中没有实际项目时,有没有办法在代码中获取 ListViewItem 高度?

我的 ListViewItem 布局:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="?android:attr/listPreferredItemHeight">
...
</LinearLayout>  

我尝试使用 Inflater 来获得它:

View convertView = LayoutInflater.from( this )
    .inflate( R.layout.mail_list_row, null );
int itemHeight = convertView.getHeight();

但它返回 0;

谢谢!

4

4 回答 4

44

试试这个,它会为你工作。

private static final int UNBOUNDED = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);

// To calculate the total height of all items in ListView call with items = adapter.getCount()
public static int getItemHeightofListView(ListView listView, int items) {
    ListAdapter adapter = listView.getAdapter();

    int grossElementHeight = 0;
    for (int i = 0; i < items; i++) {
        View childView = adapter.getView(i, null, listView);
        childView.measure(UNBOUNDED, UNBOUNDED);
        grossElementHeight += childView.getMeasuredHeight();
    }
    return grossElementHeight;
}
于 2012-09-20T13:39:21.460 回答
12

的代码的优化版本,Dwivedi Ji具有分隔高度且没有不必要的参数:

private int calculateHeight(ListView list) {

    int height = 0;

    for (int i = 0; i < list.getCount(); i++) {
        View childView = list.getAdapter().getView(i, null, list);
        childView.measure(MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED), MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        height+= childView.getMeasuredHeight();
    }

    //dividers height
    height += list.getDividerHeight() * list.getCount();

    return height;
}
于 2014-10-07T12:57:31.260 回答
5

在 android 中,只有在渲染完成时才会为视图分配宽度和高度。因此,除非您的列表至少呈现一次,否则您将不会获得 listItemHeight。您的问题的解决方案可能是您设置列表项的一些最小高度,以便您至少有一些东西可以使用,而不是硬编码高度和宽度。

于 2010-07-29T13:23:44.193 回答
3

正如上面的 hariseldon78 指出的那样,这些解决方案都没有解决真正的问题,即在呈现之前确定列表项行的高度。我遇到了同样的问题,因为我想将一些图像缩放到我的 ListView 项目行的高度,并且不想将它们缩放到固定值。如果主题导致我的行布局的其他部分中的文本高度不同,我想要高度,以便在我的适配器的 getView 例程中我可以相应地调整 bmap 的大小。我一直在努力解决 getHeight 和所有测量高度报告为零的问题,直到该行被渲染。对我来说,后来看到正确的高度为时已晚。

我的解决方案是第一次通过 getView 创建一个 onLayoutChangedListener() 并且仅针对第 0 行。一旦第一个位置 (0) 的 getView 完成执行,侦听器就会触发,届时“bottom”参数会告诉你行的高度。我将此记录在自定义适配器类变量中,因此它可以作为高度参数使用,而无需再次获取高度。

侦听器在其执行过程中注销自己。这为第 1-N 行提供了适当的高度,但不为第 0 行提供了适当的高度。对于第零行,我做了一些非常讨厌的事情。在设置另一个自定义适配器类变量来控制递归之后,我让我的侦听器再次为第 0 行调用 getView。第二次 getView(0) 运行它不会设置监听器,并且会找到一个有效的高度参数来操作,一切都很好。

代码如下 - 无需告诉我这是多么糟糕 - 如果 android 不必让它变得如此难以判断当我完成基于渲染参数填充视图时我正在创建的视图有多大表面上我不必做这种丑陋的事情,但它确实有效。对不起,如果代码格式很糟糕......

int mHeight = 0;

@Override
public View getView(final int position, View convertView, ViewGroup parent) {
... usual boiler plate stuff
    // JUST THE FIRST TIME
    if (position == 0 && mHeight == 0) {
        final View ref = convertView;
        convertView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            public void onLayoutChange(View v, int left, int top, int right,
                   int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                    ref.removeOnLayoutChangeListener(this);
                    mHeight = bottom;
                    firstTime = false;

                    //  NOW LETS REGET THE FIRST VIEW WITH THE HEIGHT CORRECT
                    int visiblePosition = getListView().getFirstVisiblePosition();
                    View view = getListView().getChildAt(0 - visiblePosition);
                    getListAdapter().getView(0, view, getListView());
                    // RECURSION LOL
            }
        });
    }

    // Configure the view for this row
    ....

    // HOW BIG IS THE VIEW?
    // NOW IF NOT FIRSTTIME (MHEIGHT != 0)
    if (mHeight != 0) {
        // DO OUR IMAGE SETUP HERE CAUSE mHeight is RIGHT!
        Log.d(TAG, "mHeight=" + mHeight);
    }

        return convertView;
}
于 2014-01-05T23:23:57.493 回答