Set ListView Height dynamically based on multiline textview inside it

半城伤御伤魂 提交于 2019-12-05 05:55:35

As Teemu mentions you need to constrain the width. Sample code below.

float px = 300 * (listView.getResources().getDisplayMetrics().density);
item.measure(View.MeasureSpec.makeMeasureSpec((int)px, View.MeasureSpec.AT_MOST), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

Could the problem be this call:

item.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED))

Here you are not constraining the width, so the TextView expands to any width it requires to show all the text in single line. Therefore you will always get the height that equals to single line text? I think you should contrain the width here to what is available from the list view.

You can try with this custom listview to avoid listhieght having multiline textview problem

 <namespace.epicurio.NestedListView
           android:id="@+id/listComments"
           android:layout_width="fill_parent"
           android:layout_height="wrap_content"
           android:layout_marginBottom="2dp"
           android:divider="#000000"
           android:dividerHeight="1.0sp">
         </namespace.epicurio.NestedListView>


    public class NestedListView extends ListView implements OnTouchListener, OnScrollListener {

        private int listViewTouchAction;
        private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 99;

        public NestedListView(Context context, AttributeSet attrs) {
            super(context, attrs);
            listViewTouchAction = -1;
            setOnScrollListener(this);
            setOnTouchListener(this);
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
                if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
                    scrollBy(0, -1);
                }
            }
        }

        @Override
        public void onScrollStateChanged(AbsListView view, int scrollState) {
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);

            int newHeight = 0;
            final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
            int heightSize = MeasureSpec.getSize(heightMeasureSpec);
            if (heightMode != MeasureSpec.EXACTLY) {
                ListAdapter listAdapter = getAdapter();
                if (listAdapter != null && !listAdapter.isEmpty()) {
                    int listPosition = 0;
                    for (listPosition = 0; listPosition < listAdapter.getCount()
                            && listPosition < MAXIMUM_LIST_ITEMS_VIEWABLE; listPosition++) {
                        View listItem = listAdapter.getView(listPosition, null, this);
                        //now it will not throw a NPE if listItem is a ViewGroup instance
                        if (listItem instanceof ViewGroup) {
                            listItem.setLayoutParams(new LayoutParams(
                                    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
                        }
                        listItem.measure(widthMeasureSpec, heightMeasureSpec);
                        newHeight += listItem.getMeasuredHeight();
                    }
                    newHeight += getDividerHeight() * listPosition;
                }
                if ((heightMode == MeasureSpec.AT_MOST) && (newHeight > heightSize)) {
                    if (newHeight > heightSize) {
                        newHeight = heightSize;
                    }
                }
            } else {
                newHeight = getMeasuredHeight();
            }
            setMeasuredDimension(getMeasuredWidth(), newHeight);
        }

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
                if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
                    scrollBy(0, 1);
                }
            }
            return false;
        }
    }

Try this code:

listview.post(new Runnable() {
    @Override
    public void run() {
        calculateListHeight(listview.getWidth());
    }
});

public void calculateListHeight(int width) {
    final ListAdapter adapter = listview.getAdapter();

    // Calculate the height of the ListView to display all items
    int totalHeight = listview.getPaddingTop() + listview.getPaddingBottom();
    for (int i = 0; i < adapter.getCount(); i++) {
        View item = adapter.getView(i, null, this);
        item.measure(
                View.MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST),
                View.MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED)
        );
        totalHeight += item.getMeasuredHeight();
    }
    ViewGroup.LayoutParams params = listview.getLayoutParams();
    params.height = totalHeight + (listview.getDividerHeight() * (adapter.getCount() - 1));

    listview.setLayoutParams(params);
    listview.requestLayout();
}

for @AlexanderAgeichenko Here is my implementation with @baradas and the Question

        int totalItemsHeight = 0;
        float px =  (customListView.getResources().getDisplayMetrics().density);
        totalItemsHeight = (int)px;
        Log.d(YOUR_TAG, " datta forloop ...  px " + px);
        Log.d(YOUR_TAG, " datta forloop ...  totalItemsHeight = (int)px=  " + totalItemsHeight);
        for (int itemPos = 0; itemPos < datta.length(); itemPos++) {
            View item = CustomListAdptr.getView(itemPos, null, customListView);
////            item.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
////                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            item.getMeasuredHeightAndState();
            Log.d(YOUR_TAG, " datta forloop item.getHeight() " + item.getHeight());
            Log.d(YOUR_TAG, " datta forloop item.getMeasuredHeight() " + item.getMeasuredHeight());
            Log.d(YOUR_TAG, " datta forloop item.getMeasuredHeightAndState() " + item.getMeasuredHeightAndState());
            int itmHeight = item.getHeight();
            Log.d(YOUR_TAG, " datta forloop ...  itmHeight " + itmHeight);
            item.measure(View.MeasureSpec.makeMeasureSpec((int)px, View.MeasureSpec.AT_MOST),
                    View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            totalItemsHeight = item.getMeasuredHeight();
//            Log.d(YOUR_TAG, " datta forloop ...  item.getMeasuredHeight() " + item.getMeasuredHeight());
            Log.d(YOUR_TAG, " datta forloop ...  totalItemsHeight=item.getMeasuredHeight()  " + totalItemsHeight);
        }
        Log.d(YOUR_TAG, " datta forloop ...  totalItemsHeight ==  " + totalItemsHeight);

        // Get total height of all item dividers.
        int totalDividersHeight = customListView.getDividerHeight() *
                (numberOfItems - 1);
        // Get padding
        int totalPadding = customListView.getPaddingTop() + customListView.getPaddingBottom();

        // Set list height.
        ViewGroup.LayoutParams params = customListView.getLayoutParams();
        params.height = totalItemsHeight + totalDividersHeight + totalPadding;
        customListView.setLayoutParams(params);
        customListView.requestLayout();
        customListView.canScrollList(0);

And the out put was

D/YOUR_TAG:  onViewCompleted() if(success) setting the list data
D/YOUR_TAG:  datta counts 3
D/YOUR_TAG:  datta forloop ...  px 2.0
D/YOUR_TAG:  datta forloop ...  totalItemsHeight = (int)px=  2
D/YOUR_TAG:  datta forloop item.getMeasuredHeightAndState() 0
D/YOUR_TAG:  datta forloop item.getMeasuredHeight() 0
D/YOUR_TAG:  datta forloop item.getHeight() 0
D/YOUR_TAG:  datta forloop ...  itmHeight 0
D/YOUR_TAG:  datta forloop ...  totalItemsHeight=item.getMeasuredHeight()  1709
D/YOUR_TAG:  datta forloop item.getMeasuredHeightAndState() 0
D/YOUR_TAG:  datta forloop item.getMeasuredHeight() 0
D/YOUR_TAG:  datta forloop item.getHeight() 0
D/YOUR_TAG:  datta forloop ...  itmHeight 0
D/YOUR_TAG:  datta forloop ...  totalItemsHeight=item.getMeasuredHeight()  1709
D/YOUR_TAG:  datta forloop item.getMeasuredHeightAndState() 0
D/YOUR_TAG:  datta forloop item.getMeasuredHeight() 0
D/YOUR_TAG:  datta forloop item.getHeight() 0
D/YOUR_TAG:  datta forloop ...  itmHeight 0
D/YOUR_TAG:  datta forloop ...  totalItemsHeight=item.getMeasuredHeight()  1709
D/YOUR_TAG:  datta forloop ...  totalItemsHeight ==  1709
D/YOUR_TAG:  getView() -> unit_option= 0 :: class java.lang.String

WITH 110 float px = 110 *(customListView.getResources().getDisplayMetrics().density);

D/YOUR_TAG:  onViewCompleted() if(success) setting the list data
D/YOUR_TAG:  datta counts 3
D/YOUR_TAG:  datta forloop ...  px 220.0
D/YOUR_TAG:  datta forloop ...  totalItemsHeight = (int)px=  220
D/YOUR_TAG:  datta forloop item.getMeasuredHeightAndState() 0
D/YOUR_TAG:  datta forloop item.getMeasuredHeight() 0
D/YOUR_TAG:  datta forloop item.getHeight() 0
D/YOUR_TAG:  datta forloop ...  itmHeight 0
D/YOUR_TAG:  datta forloop ...  totalItemsHeight=item.getMeasuredHeight()  159
D/YOUR_TAG:  datta forloop item.getMeasuredHeightAndState() 0
D/YOUR_TAG:  datta forloop item.getMeasuredHeight() 0
D/YOUR_TAG:  datta forloop item.getHeight() 0
D/YOUR_TAG:  datta forloop ...  itmHeight 0
D/YOUR_TAG:  datta forloop ...  totalItemsHeight=item.getMeasuredHeight()  159
D/YOUR_TAG:  datta forloop item.getMeasuredHeightAndState() 0
D/YOUR_TAG:  datta forloop item.getMeasuredHeight() 0
D/YOUR_TAG:  datta forloop item.getHeight() 0
D/YOUR_TAG:  datta forloop ...  itmHeight 0
D/YOUR_TAG:  datta forloop ...  totalItemsHeight=item.getMeasuredHeight()  159
D/YOUR_TAG:  datta forloop ...  totalItemsHeight ==  159
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!