Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>This thread has helped me find a solution for a similar problem I've been struggling with for a while. It is also based on intercepting touch events. In this case the syncing works for multiple listviews and is entirely symmetric. </p> <p>The major challenge was to prevent list item clicks to propagate to the other listviews. I need clicks and long clicks dispatched only by the listview that initially received the touch event, including in particular the highlight feedback when you just touch down on an item (intercepting onClick event is no use since it's too late in the calling hierarchy).</p> <p>The key to this is intercepting the touch event twice. First, the initial touch event is relayed to the other listviews. The same onTouch handler function catches these and feeds them to a GestureDetector. In the <code>GestureDetector</code> callbacks the static touch events (<code>onDown</code> etc.) are consumed (<code>return true</code>) whereas the motion gestures aren't (<code>return false</code>) such that they can be further dispatched by the view itself and trigger the scrolling. </p> <p>Using <code>setPositionFromTop</code> inside <code>onScroll</code> didn't work for me because it makes the scrolling behavior extremely sluggish. OnScroll is used instead to align initial scroll positions as new ListViews are added to the Syncer. </p> <p>The only problem that persists so far is the one brought up by s1ni5t3r above. If you double-fling the listView then they still become disconnected. </p> <pre><code>public class ListScrollSyncer implements AbsListView.OnScrollListener, OnTouchListener, OnGestureListener { private GestureDetector gestureDetector; private Set&lt;ListView&gt; listSet = new HashSet&lt;ListView&gt;(); private ListView currentTouchSource; private int currentOffset = 0; private int currentPosition = 0; public void addList(ListView list) { listSet.add(list); list.setOnTouchListener(this); list.setSelectionFromTop(currentPosition, currentOffset); if (gestureDetector == null) gestureDetector = new GestureDetector(list.getContext(), this); } public void removeList(ListView list) { listSet.remove(list); } public boolean onTouch(View view, MotionEvent event) { ListView list = (ListView) view; if (currentTouchSource != null) { list.setOnScrollListener(null); return gestureDetector.onTouchEvent(event); } else { list.setOnScrollListener(this); currentTouchSource = list; for (ListView list : listSet) if (list != currentTouchSource) list.dispatchTouchEvent(event); currentTouchSource = null; return false; } } public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { if (view.getChildCount() &gt; 0) { currentPosition = view.getFirstVisiblePosition(); currentOffset = view.getChildAt(0).getTop(); } } public void onScrollStateChanged(AbsListView view, int scrollState) { } // GestureDetector callbacks public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; } public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } public boolean onSingleTapUp(MotionEvent e) { return true; } public boolean onDown(MotionEvent e) { return true; } public void onLongPress(MotionEvent e) { } public void onShowPress(MotionEvent e) { } } </code></pre> <p>edit: the double-fling issue can be resolved by using a state variable.</p> <pre><code>private boolean scrolling; public boolean onDown(MotionEvent e) { return !scrolling; } public void onScrollStateChanged(AbsListView view, int scrollState) { scrolling = scrollState != SCROLL_STATE_IDLE; } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload