I am developing an application with ViewPager as a menu. Each fragment has a bunch of child views, which can be ListView , ScrollView , LinearLayout , etc. ... One of these fragments has a settings button that switches the settings panel ( LinearLayout wrapper) using ScrollView and some LinearLayout (buttons) and SeekBar as subsidiaries. This settings panel animates with an animation of sliding up or down (when fired), and when it is visible, I will disable the paging ViewPager :
@Override public boolean onTouchEvent(MotionEvent event) { if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE) { return true; } return super.onTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent event) { if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE) { return true; } return super.onInterceptTouchEvent(event); } public boolean isPagingEnabled() { return pagingEnabled; } public void setPagingEnabled(boolean pagingEnabled) { this.pagingEnabled = pagingEnabled; }
But this caused a problem: every time the panel rises, all child views do not receive OnTouchEvent , and so I added GestureDetector.SimpleOnGestureListener :
protected class YScrollDetector extends GestureDetector.SimpleOnGestureListener { @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { Log.i(C.TAG, "distanceX " + distanceX + " distanceY " + distanceY); return Math.abs(distanceY) < Math.abs(distanceX); } }
and changed my ViewPager onInterceptTouchEvent to:
@Override public boolean onInterceptTouchEvent(MotionEvent event) { if (!pagingEnabled && event.getAction() == MotionEvent.ACTION_MOVE && (mGestureDetector != null && mGestureDetector.onTouchEvent(event))) { return true; } return super.onInterceptTouchEvent(event); }
This works, the panel buttons get them onClick, scroll ListView, etc .... but it doesn’t work so perfectly because Math.abs(distanceY) < Math.abs(distanceX) is not so accurate. If I quickly scroll up and down either diagonally, or if I touch the button with a small hit, onInterceptTouchEvent will return true because mGestureDetector.onTouchEvent(event) will also return true .
After doing some googling, I came across this:
viewPager.requestDisallowInterceptTouchEvent(true);
And I tried something like this:
myListView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { viewPager.requestDisallowInterceptTouchEvent(true); return false; } });
And it works very well because ViewPager.onInterceptTouchEvent it first called MotionEvent.ACTION_DOWN and then myListView.setOnTouchListener it called right after and disables the rest of the MotionEvent actions (MOVE and UP), and I can quickly scroll up, down, sides, etc. .d. The ViewPager page ViewPager wont, but the ListView performs like a charm.
But the problem still remains, I have to add this requestDisallowInterceptTouchEvent(true) to all OnTouchEvent child views, and this is not elegant code.
So my question is: am I on the right track? Is there anyway to avoid adding this listener to all child views of the panel (of course, if I have to do it in the most usual way)?
Thank you for your time.