5

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

}


}
Marc Van Daele
  • 2,856
  • 1
  • 26
  • 52
  • I think I can rephrase the question as "is it possible for a child view to receive the TouchEvents consumed by the ListView parent". This would allow the ListView to handle the vertical component of my move and the HorizontalScrollView could handle the horizontal component of the move. – Marc Van Daele Nov 09 '11 at 09:22

4 Answers4

5

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.

jenzz
  • 7,239
  • 6
  • 49
  • 69
Marc Van Daele
  • 2,856
  • 1
  • 26
  • 52
1

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

Shailendra Singh Rajawat
  • 8,172
  • 3
  • 35
  • 40
  • My ListView is the parent component, the HorizontalScrollViews are the children of the ListView (so it seems to be the other way around as your scenario). I use no XML layout; all views are created in the code. – Marc Van Daele Nov 07 '11 at 12:34
0

Android has a concept called touch slop. Here's a similar question already answered: Android ACTION_MOVE Threshold

Community
  • 1
  • 1
Matt W
  • 686
  • 1
  • 9
  • 12
  • I don't think the mTouchSlop is relevant here. The original problem was that a minor vertical scroll stops the horizontal scroll because at that point ListView is taking over. – Marc Van Daele Oct 30 '14 at 13:09
0

Best way to do this.

put given code on your horizontal listview onScroll method it work perfact

   ViewParent view_parent = getParent();
   if (view_parent != null) 
   {
     view_parent.requestDisallowInterceptTouchEvent(true);
   }
Ram
  • 1,408
  • 13
  • 29