Android - 获取ListView项目高度?

时间:2010-07-29 10:17:20

标签: android user-interface listview layout listviewitem

当列表中没有实际项目时,有没有办法在代码中获取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;

谢谢!

3 个答案:

答案 0 :(得分:11)

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;
}

答案 1 :(得分:4)

在android中,只有在渲染完成时才会为视图指定宽度和高度。所以,除非你的列表被删除,否则你将无法获得listItemHeight。您的问题的解决方案可能是您设置列表项的最小高度,以便您至少使用某些内容而不是硬编码高度和宽度。

答案 2 :(得分:2)

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

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

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

代码如下 - 没有必要告诉我AWFUL是怎么回事 - 如果android没有必要让它变得非常难以分辨我创建的视图有多大,那就是当我完成基于渲染的视图填充时表面的parms我不必做这个丑陋但它的工作原理。对不起,如果代码格式很糟糕......

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;
}