The best way to disable swap ViewPager

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.

+6
source share
1 answer

Disabling paging should be as simple as returning false from onInterceptTouchEvent and onTouchEvent . You do not need additional gesture detection to bypass the ViewPager . Extend ViewPager as follows:

 public class MyViewPager extends ViewPager { private boolean pagingEnabled = true; public MyViewPager(Context context) { super(context); } public MyViewPager(Context context, AttributeSet attrs) { super(context, attrs); } public void setPagingEnabled(boolean pagingEnabled) { this.pagingEnabled = pagingEnabled; } @Override public boolean onInterceptTouchEvent(MotionEvent event) { return pagingEnabled && super.onInterceptTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { return pagingEnabled && super.onTouchEvent(event); } } 

I use the same thing (with a different name) for the same reason in one of my applications, and it definitely works.

+16
source

Source: https://habr.com/ru/post/975537/


All Articles