搜索

首页  >  问答  >  正文

adapter - Android布局——listview会根据数据数量自动调节高度吗

最近在看一个项目的源码,有一个实现listview里嵌套listview的功能,实现方式是用Adapter嵌套Adapter。但是在主Adapter里,有一个函数用于更改子listview的布局高度。

public static void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            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.getpiderHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }

显然这个函数会根据adapter中数据的个数调节listview布局的高度,那么为什么listview不会自己调节呢?

阿神阿神2769 天前359

全部回复(2)我来回复

  • 大家讲道理

    大家讲道理2017-04-17 13:32:38

    因为嵌套的ListView不需要也不应该能滚动

    所以在代码中 需要将嵌套的ListView调整到刚好能显示所有Child的高度

    而对于ListView本身而言,它是不关心自身高度和是否能显示下所有Child的,因为就原始设计上而言,它是一个可以滚动的组件.


    你也可以自己阅读下面这段代码来看看ListView的measure自身高度的逻辑
    看看MeasureSpec.UNSPECIFIED模式下ListView的高度是怎么来的

     @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            // Sets up mListPadding
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            int widthMode = MeasureSpec.getMode(widthMeasureSpec);
            int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int widthSize = MeasureSpec.getSize(widthMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
            int childWidth = 0;
            int childHeight = 0;
            int childState = 0;
    
            mItemCount = mAdapter == null ? 0 : mAdapter.getCount();
            if (mItemCount > 0 && (widthMode == MeasureSpec.UNSPECIFIED ||
                    heightMode == MeasureSpec.UNSPECIFIED)) {
                final View child = obtainView(0, mIsScrap);
    
                measureScrapChild(child, 0, widthMeasureSpec);
    
                childWidth = child.getMeasuredWidth();
                childHeight = child.getMeasuredHeight();
                childState = combineMeasuredStates(childState, child.getMeasuredState());
    
                if (recycleOnMeasure() && mRecycler.shouldRecycleViewType(
                        ((LayoutParams) child.getLayoutParams()).viewType)) {
                    mRecycler.addScrapView(child, 0);
                }
            }
    
            if (widthMode == MeasureSpec.UNSPECIFIED) {
                widthSize = mListPadding.left + mListPadding.right + childWidth +
                        getVerticalScrollbarWidth();
            } else {
                widthSize |= (childState&MEASURED_STATE_MASK);
            }
    
            if (heightMode == MeasureSpec.UNSPECIFIED) {
                heightSize = mListPadding.top + mListPadding.bottom + childHeight +
                        getVerticalFadingEdgeLength() * 2;
            }
    
            if (heightMode == MeasureSpec.AT_MOST) {
                // TODO: after first layout we should maybe start at the first visible position, not 0
                heightSize = measureHeightOfChildren(widthMeasureSpec, 0, NO_POSITION, heightSize, -1);
            }
    
            setMeasuredDimension(widthSize , heightSize);
            mWidthMeasureSpec = widthMeasureSpec;        
        }
    

    回复
    0
  • 迷茫

    迷茫2017-04-17 13:32:38

    因为ListView要复用ConvertView

    回复
    0
  • 取消回复