10

Possible Duplicate:
Listview inside ScrollView is not scrolling on Android

I have a ListView inside a ScrollView and the problem is that the ScrollView is scrolling but ListView doesn't scroll. I think this is happening because of that ScrollView. Does anyone have a solution for this issue?

Community
  • 1
  • 1
Tarun Tak
  • 401
  • 1
  • 5
  • 12
  • stop arguing about it, it wont solve the question, someone already find the solution, this is the ANSWER by Moisés Olmedo : http://stackoverflow.com/questions/6210895/listview-inside-scrollview-is-not-scrolling-on-android?rq=1 – Bhimbim Mar 03 '14 at 03:59

4 Answers4

6

ListViews have built-in scrolling capabilities. Encapsulate it in any other layout like a LinearLayout or RelativeLayout.

JDJ
  • 4,198
  • 3
  • 22
  • 43
Rohit Mandiwal
  • 9,466
  • 4
  • 61
  • 75
6

I required having a listview inside a scrollview in order to prevent the entire screen from being extremely long. This allows you have to set the number of items displayed on the list, while the rest will be scrolled.

I use the following class in my app and so far it seems to work terrific.

 public class NestedListView extends ListView implements OnScrollListener,
        OnTouchListener {
    private int listViewTouchAction;
    private static final int MAXIMUM_LIST_ITEMS_VIEWABLE = 4;

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

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

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

    @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);
                    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) {
        listViewTouchAction = event.getAction();
        if (getAdapter() != null && getAdapter().getCount() > MAXIMUM_LIST_ITEMS_VIEWABLE) {
            if (listViewTouchAction == MotionEvent.ACTION_MOVE) {
                scrollBy(0, 1);
            }
        }
        return false;
    }
}
SALMAN
  • 3,909
  • 1
  • 24
  • 21
Jeff
  • 334
  • 4
  • 12
  • The problem I have with this solution is that it costs huge amounts of CPU power. In the onMeasure method you are asking the listadapter to recreate every view you ask for, this will make the whole app very slow. I think you should cache the views you ask for and only recreate them when they are invalid. – Willem Meints Jan 23 '12 at 14:26
  • While I haven't noticed any problems with this solution on my Atrix, I'm sure it could be a problem on older devices. – Jeff Apr 19 '12 at 02:01
2

Use the following method and enjoy!

    private void setListViewScrollable(final ListView list) {
    list.setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            listViewTouchAction = event.getAction();
            if (listViewTouchAction == MotionEvent.ACTION_MOVE)
            {
                list.scrollBy(0, 1);
            }
            return false;
        }
    });
    list.setOnScrollListener(new OnScrollListener() {
        @Override
        public void onScrollStateChanged(AbsListView view,
                int scrollState) {
        }

        @Override
        public void onScroll(AbsListView view, int firstVisibleItem,
                int visibleItemCount, int totalItemCount) {
            if (listViewTouchAction == MotionEvent.ACTION_MOVE)
            {
                list.scrollBy(0, -1);
            }
        }
    });
}

listViewTouchAction is a global integer value. If you can replace the line

list.scrollBy(0, 1);

with something else please share it with us.

Bobs
  • 21,870
  • 33
  • 134
  • 221
1

You shouldn't nest a ListView inside a ScrollView.

If you're trying to scroll some other views along with the ListView, you might check out this answer.

Community
  • 1
  • 1
Matthew Willis
  • 44,037
  • 10
  • 96
  • 87