Android - 获取ListView项目高度?

发布于 2024-09-11 18:23:11 字数 535 浏览 7 评论 0原文

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

谢谢!

Is there a way to get ListViewItem height in code, when there is no actual items in list?

My ListViewItem layout:

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

I have tried to get it using Inflater:

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

But it's return 0;

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

起风了 2024-09-18 18:23:11

试试这个,它会对你有用。

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

Try this, it will work for you.

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;
}
初懵 2024-09-18 18:23: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;
}

optimized version of Dwivedi Ji's code with dividers height and without unnecessary params:

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;
}
痞味浪人 2024-09-18 18:23:11

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

In android a view is assigned Width and Height only when its rendering is complete. So unless you list is rendered atleast once you won't get listItemHeight. Solution to your problem could be that you set some min Height of list Item so that you have atleast something to work with instead of Hard Coding height and width.

如梦 2024-09-18 18:23:11

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

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

侦听器在其执行过程中注销自身。这为第 1-N 行提供了正确的高度,但没有为第 0 行提供了正确的高度。对于第 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;
}

As hariseldon78 above points out none of these solutions fix the REAL problem which is determining the height of the list item row BEFORE it is rendered. I had the same problem as I wanted to scale some images to the height of my ListView item rows, and did not want to scale them to a fixed value. If the theme caused the text in other parts of my row layout to vary in height, I wanted the height so that in my getView routine of my adapter I could resize the bmap accordingly. I was struggling with the problem that getHeight and all the measured heights report zero until the row has been rendered. FOr me seeing the heights correct later was too late.

My solution is to create an onLayoutChangedListener() the first time through getView and only for row 0. The listener will trigger as soon as getView for the first position (0) completes executing, and at that time the "bottom" parameter will tell you the height of the row. I record this in a custom adapter class variable so it is available as a height parameter without having to fetch the height again.

The listener unregisters itself as part of its execution. This provides the proper height for rows 1-N but not for row zero. For row zero I did something really nasty. I had my listener call getView AGAIN for row 0 after setting another custom adapter class variable to control the recursion. The second time getView(0) runs it will not setup the listener, and will find a valid parameter for height to operate with and all is good.

Code is below - no need to tell me how AWFUL this is - if android didn't have to make it so freaking hard to tell how big the view I am creating is when I am done populating the view's based on the rendering parms for the surface I wouldn't have to do this ugliness but it works. Sorry if the code formatting is awful ...

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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文