根据里面的多行textview动态设置ListView Height

时间:2015-03-24 05:20:35

标签: android android-layout listview android-listview android-adapter

我正在使用基本适配器动态设置列表视图中的数据。我试图动态设置listview高度。如果里面的textview是单行的话,它可以很好地工作。但是,如果textview是多行的,则高度设置不正确。仅考虑单行textview设置高度。如何正确设置包含多行textview的列表视图项的高度。这是代码:

片段代码:

ListView mlistNews=(ListView)rootView.findViewById(R.id.news_listView);
mlistNews.setAdapter(new NewsAdapter(getActivity(),params_news));
Utils.setListViewHeightBasedOnItems(mlistNews);

效用函数:

public static boolean setListViewHeightBasedOnItems(ListView listView) {

    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter != null) {

        int numberOfItems = listAdapter.getCount();

        // Get total height of all items.
        int totalItemsHeight = 0;
        for (int itemPos = 0; itemPos < numberOfItems; itemPos++) {
            View item = listAdapter.getView(itemPos, null, listView);
            item.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
            totalItemsHeight += item.getMeasuredHeight();
        }

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

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

        return true;

    } else {
        return false;
    }

}

dashboard_list_news.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp">
<TextView
    android:layout_width="0dp"
    android:id="@+id/news_item_text"
    android:layout_weight="1"
    android:layout_height="wrap_content"
    android:layout_gravity="left|center_vertical"
    android:layout_marginLeft="5dp"/>

<ImageView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:src="@drawable/chevron"
    android:layout_gravity="center_vertical|right"
    android:layout_marginLeft="5dp"
    android:layout_marginRight="10dp" />

</LinearLayout>

的ListView:

<ListView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@drawable/rounded_shape_list"
            android:id="@+id/news_listView"
            android:paddingTop="5dp"
            android:paddingBottom="5dp"
            android:divider="#6DCB99"
            android:dividerHeight="1dp" />

5 个答案:

答案 0 :(得分:6)

正如Teemu所提到的,你需要约束宽度。示例代码如下。

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

答案 1 :(得分:3)

问题可能就是这个电话:

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

这里您没有约束宽度,因此TextView扩展到显示单行所有文本所需的任何宽度。因此,您将始终获得等于单行文本的高度? 我认为你应该将宽度与列表视图中的宽度相对应。

答案 2 :(得分:0)

您可以尝试使用此自定义列表视图,以避免列表中出现多行文本视图问题

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

答案 3 :(得分:0)

试试这段代码:

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

答案 4 :(得分:0)

@AlexanderAgeichenko 这是我对@baradas和问题的实现

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

输出是

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