Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HorizontalScrollView inside ListView: minor vertical scroll stops horizontal scroll

In my example activity, I have
- a ListView containing
- multiple HorizontalScrollView containing
- a set of TextView

The horizontal scrolling experience is rather bad though.
When I initiate a horizontal scroll (or fling), I must be very careful to make it work.

As soon as the horizontal scroll contains a (small) vertical component, the vertical ListView scrolling takes over and stops the horizontal scrolling completely.

Any suggestion on how to improve this?

Thanks in advance,

Marc

import android.app.Activity;
import android.database.DataSetObserver;
import android.os.Bundle;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.TextView;

public class Test extends Activity 
{
private final static int N = 20;//number of HorizontalScrollView
private final static int M = 20;//number of TextViews inside a single HorizontalScrollView


@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    LinearLayout layout = new LinearLayout(this);
    //create a list of HorizontalScrollViews
    final HorizontalScrollView[] hors = new HorizontalScrollView[N];
    for (int i = 0; i < hors.length; i++)
    {
        hors[i] = new HorizontalScrollView(this, null);
        hors[i].setMinimumHeight(60);
        LinearLayout ll = new LinearLayout(this);
        ll.setOrientation(LinearLayout.HORIZONTAL);
        hors[i].addView(ll);
        for (int j = 0; j < M; j++)
        {
            TextView t = new TextView(Test.this);
            t.setText("HorizontalScrollView: "+i+"; TextView: "+j);
            t.setMinimumHeight(40);
            ll.addView(t);
        }
    }
    //add a ListView
    ListView list = new ListView(this);
    layout.addView(list);
    list.setAdapter(new BaseAdapter()
    {

        @Override
        public View getView(int position, View convertView, ViewGroup parent)
        {
            return hors[position];
        }

        @Override
        public long getItemId(int position)
        {
            return 0;
        }

        @Override
        public Object getItem(int position)
        {
            return hors[position];
        }

        @Override
        public int getCount()
        {
            return N;
        }
    });

    setContentView(layout);

}


}
like image 991
Marc Van Daele Avatar asked Nov 07 '11 11:11

Marc Van Daele


2 Answers

The problem is that ListView (or rather its parent AbsListView) implements onInterceptTouchEvent and hence ListView can intercept all touch events as soon as it considers it is in a better position to handle them.

This can be avoided by calling requestDisallowInterceptTouchEvent, e.g. by subclassing HorizontalScrollView and in its dispatchTouchEvent:

public boolean dispatchTouchEvent(MotionEvent ev)
{
  boolean ret = super.dispatchTouchEvent(ev);
  if(ret) 
  {
    requestDisallowInterceptTouchEvent(true);
  }
  return ret;
}       

It needs some refinement (like only call requestDisallowInterceptTouchEvent if the horizontal component is larger than the vertical one) since now it hardly ever allows the ListView to take control.

like image 198
Marc Van Daele Avatar answered Sep 30 '22 12:09

Marc Van Daele


although i did not dig inside your code, but general mistake people do is insert listView inside ScrollView .

as listview is auto-Scrolled so keep it outside scrollView while other things might be in scrollView .

check if this is the scenario , else share XML Layout

like image 27
Shailendra Singh Rajawat Avatar answered Sep 30 '22 13:09

Shailendra Singh Rajawat