How can I put a ListView into a ScrollView without

2018-12-31 00:20发布

I've searched around for solutions to this problem, and the only answer I can find seems to be "don't put a ListView into a ScrollView". I have yet to see any real explanation for why though. The only reason I can seem to find is that Google doesn't think you should want to do that. Well I do, so I did.

So the question is, how can you place a ListView into a ScrollView without it collapsing to its minimum height?

27条回答
墨雨无痕
2楼-- · 2018-12-31 00:49

All these answers are wrong!!! If you are trying to put a listview in a scroll view you should re-think your design. You are trying to put a ScrollView in a ScrollView. Interfering with the list will hurt list performance. It was designed to be like this by Android.

If you really want the list to be in the same scroll as the other elements, all you have to do is add the other items into the top of the list using a simple switch statement in your adapter:

class MyAdapter extends ArrayAdapter{

    public MyAdapter(Context context, int resource, List objects) {
        super(context, resource, objects);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
         ViewItem viewType = getItem(position);

        switch(viewType.type){
            case TEXTVIEW:
                convertView = layouteInflater.inflate(R.layout.textView1, parent, false);

                break;
            case LISTITEM:
                convertView = layouteInflater.inflate(R.layout.listItem, parent, false);

                break;            }


        return convertView;
    }


}

The list adapter can handle everything since it only renders what is visible.

查看更多
唯独是你
3楼-- · 2018-12-31 00:51

You should not put a ListView in a ScrollView because a ListView already is a ScrollView. So that would be like putting a ScrollView in a ScrollView.

What are you trying to accomplish?

查看更多
像晚风撩人
4楼-- · 2018-12-31 00:52

This is a combination of the answers by DougW, Good Guy Greg, and Paul. I found it was all needed when trying to use this with a custom listview adapter and non-standard list items otherwise the listview crashed the application (also crashed with the answer by Nex):

public void setListViewHeightBasedOnChildren(ListView listView) {
        ListAdapter listAdapter = listView.getAdapter();
        if (listAdapter == null) {
            return;
        }

        int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
        for (int i = 0; i < listAdapter.getCount(); i++) {
            View listItem = listAdapter.getView(i, null, listView);
            if (listItem instanceof ViewGroup)
                listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
            listItem.measure(0, 0);
            totalHeight += listItem.getMeasuredHeight();
        }

        ViewGroup.LayoutParams params = listView.getLayoutParams();
        params.height = totalHeight + (listView.getDividerHeight() * (listAdapter.getCount() - 1));
        listView.setLayoutParams(params);
    }
查看更多
栀子花@的思念
5楼-- · 2018-12-31 00:52

I converted @DougW's Utility into C# (used in Xamarin). The following works fine for fixed-height items in the list, and is going to be mostly fine, or at least a good start, if only some of the items are a bit bigger than the standard item.

// You will need to put this Utility class into a code file including various
// libraries, I found that I needed at least System, Linq, Android.Views and 
// Android.Widget.
using System;
using System.Linq;
using Android.Views;
using Android.Widget;

namespace UtilityNamespace  // whatever you like, obviously!
{
    public class Utility
    {
        public static void setListViewHeightBasedOnChildren (ListView listView)
        {
            if (listView.Adapter == null) {
                // pre-condition
                return;
            }

            int totalHeight = listView.PaddingTop + listView.PaddingBottom;
            for (int i = 0; i < listView.Count; i++) {
                View listItem = listView.Adapter.GetView (i, null, listView);
                if (listItem.GetType () == typeof(ViewGroup)) {
                    listItem.LayoutParameters = new LinearLayout.LayoutParams (ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
                }
                listItem.Measure (0, 0);
                totalHeight += listItem.MeasuredHeight;
            }

            listView.LayoutParameters.Height = totalHeight + (listView.DividerHeight * (listView.Count - 1));
        }
    }
}

Thanks @DougW, this got me out of a tight spot when I had to work with OtherPeople'sCode. :-)

查看更多
梦该遗忘
6楼-- · 2018-12-31 00:56

Here is my version of the code that calculates total height of the list view. This one works for me:

   public static void setListViewHeightBasedOnChildren(ListView listView) {
    ListAdapter listAdapter = listView.getAdapter();
    if (listAdapter == null || listAdapter.getCount() < 2) {
        // pre-condition
        return;
    }

    int totalHeight = 0;
    int widthMeasureSpec = View.MeasureSpec.makeMeasureSpec(BCTDApp.getDisplaySize().width, View.MeasureSpec.AT_MOST);
    int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
    ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);

    for (int i = 0; i < listAdapter.getCount(); i++) {
        View listItem = listAdapter.getView(i, null, listView);
        if (listItem instanceof ViewGroup) listItem.setLayoutParams(lp);
        listItem.measure(widthMeasureSpec, heightMeasureSpec);
        totalHeight += listItem.getMeasuredHeight();
    }

    totalHeight += listView.getPaddingTop() + listView.getPaddingBottom();
    totalHeight += (listView.getDividerHeight() * (listAdapter.getCount() - 1));
    ViewGroup.LayoutParams params = listView.getLayoutParams();
    params.height = totalHeight;
    listView.setLayoutParams(params);
    listView.requestLayout();
}
查看更多
初与友歌
7楼-- · 2018-12-31 00:57

When we place ListView inside ScrollView two problems arise. One is ScrollView measures its children in UNSPECIFIED mode, so ListView sets its own height to accommodate only one item(I don't know why), another is ScrollView intercepts the touch event so ListView does not scrolls.

But we can place ListView inside ScrollView with some workaround. This post, by me, explains the workaround. By this workaround we can also retain ListView's recycling feature as well.

查看更多
登录 后发表回答