Android 中 DrawerLayout + ViewPager 怎么解决滑动冲突?
2017-06-09 00:00
585 查看
DrawerLayout 是 Android 官方的侧滑菜单控件,而 ViewPager 相信大家都很熟悉了。今天这里就讲一下当在 DrawerLayout 中嵌套 ViewPager 时,要如何解决滑动冲突的问题,效果如下:
首先,让我们先来解决 DrawerLayout 和 ViewPager 的侧滑事件冲突。当 DrawerLayout 中嵌套 ViewPager 时,侧滑默认是执行 DrawerLayout 的侧滑事件,因为 Android 的事件分发是从 外层 ViewGroup 向里逐级传递到 View 的。
所以会先执行 DrawerLayout 的 onTouchEvent 方法:
可以看到在最后始终返回 wantTouchEvents,也就是返回 true,意味着点击事件在 DrawerLayout 就被消费掉了,无法传到 ViewPager。
所以,我们像下面这样,监听当 Drawer 打开时,将 DrawerLayout 设置为 LOCK_MODE_LOCKED_OPEN,这样在 Drawer 被打开时,就能够触发 ViewPager 的滑动事件了。
但是,当侧边栏的 ViewPager 滑动到最后一页,再向左滑动时,我们会希望能够自然的关闭 Drawer。这就需要我们监听 ViewPager 的 PageChange 事件,当滑动到最后一页时,将 DrawerLay
3ff0
out 的 LockMode 设置回 LOCK_MODE_UNLOCKED。
这里,选择在 DrawerFragment(也就是定义侧边栏的 Fragment) 中定义一个接口:
然后让 MainActivity 实现这个接口:
再在 DrawerFragment 中 ViewPager 的 PageChange 事件中使用:
这样我们就解决了 DrawerLayout 和 ViewPager 的侧滑事件冲突问题,剩下最后一个要处理的小问题就是在点击空白区域时,也想要关闭侧边栏,这个就只需要:
到这里就大功告成啦!
作者:Hevin - 极光开发者
原文:Android 中 DrawerLayout + ViewPager 怎么解决滑动冲突?
知乎专栏:极光日报
首先,让我们先来解决 DrawerLayout 和 ViewPager 的侧滑事件冲突。当 DrawerLayout 中嵌套 ViewPager 时,侧滑默认是执行 DrawerLayout 的侧滑事件,因为 Android 的事件分发是从 外层 ViewGroup 向里逐级传递到 View 的。
所以会先执行 DrawerLayout 的 onTouchEvent 方法:
@Override public boolean onTouchEvent(MotionEvent ev) { mLeftDragger.processTouchEvent(ev); mRightDragger.processTouchEvent(ev); final int action = ev.getAction(); boolean wantTouchEvents = true; switch (action & MotionEventCompat.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { final float x = ev.getX(); final float y = ev.getY(); mInitialMotionX = x; mInitialMotionY = y; mDisallowInterceptRequested = false; mChildrenCanceledTouch = false; break; } case MotionEvent.ACTION_UP: { final float x = ev.getX(); final float y = ev.getY(); boolean peekingOnly = true; final View touchedView = mLeftDragger.findTopChildUnder((int) x, (int) y); if (touchedView != null && isContentView(touchedView)) { final float dx = x - mInitialMotionX; final float dy = y - mInitialMotionY; final int slop = mLeftDragger.getTouchSlop(); if (dx * dx + dy * dy < slop * slop) { // Taps close a dimmed open drawer but only if it isn't locked open. final View openDrawer = findOpenDrawer(); if (openDrawer != null) { peekingOnly = getDrawerLockMode(openDrawer) == LOCK_MODE_LOCKED_OPEN; } } } closeDrawers(peekingOnly); mDisallowInterceptRequested = false; break; } case MotionEvent.ACTION_CANCEL: { closeDrawers(true); mDisallowInterceptRequested = false; mChildrenCanceledTouch = false; break; } } return wantTouchEvents; }
可以看到在最后始终返回 wantTouchEvents,也就是返回 true,意味着点击事件在 DrawerLayout 就被消费掉了,无法传到 ViewPager。
所以,我们像下面这样,监听当 Drawer 打开时,将 DrawerLayout 设置为 LOCK_MODE_LOCKED_OPEN,这样在 Drawer 被打开时,就能够触发 ViewPager 的滑动事件了。
mDrawerLayout.addDrawerListener(new DrawerLayout.DrawerListener() { @Override public void onDrawerSlide(View drawerView, float slideOffset) { } @Override public void onDrawerOpened(View drawerView) { mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN); } @Override public void onDrawerClosed(View drawerView) { mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); } @Override public void onDrawerStateChanged(int newState) { } });
但是,当侧边栏的 ViewPager 滑动到最后一页,再向左滑动时,我们会希望能够自然的关闭 Drawer。这就需要我们监听 ViewPager 的 PageChange 事件,当滑动到最后一页时,将 DrawerLay
3ff0
out 的 LockMode 设置回 LOCK_MODE_UNLOCKED。
这里,选择在 DrawerFragment(也就是定义侧边栏的 Fragment) 中定义一个接口:
/** * 监听侧边栏的页面选择。 */ public interface OnDrawerPageChangeListener { void onPageSelected(boolean isLast); }
然后让 MainActivity 实现这个接口:
@Override public void onPageSelected(boolean isLast) { if (isLast) { mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED); } else if (mDrawerLayout.getDrawerLockMode(GravityCompat.START) == DrawerLayout.LOCK_MODE_UNLOCKED) { mDrawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_OPEN); } }
再在 DrawerFragment 中 ViewPager 的 PageChange 事件中使用:
final OnDrawerPageChangeListener drawerPageChangeListener = (OnDrawerPageChangeListener) getActivity(); mViewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } @Override public void onPageSelected(int position) { if (position == fragmentList.size() - 1) { drawerPageChangeListener.onPageSelected(true); } else { drawerPageChangeListener.onPageSelected(false); } } @Override public void onPageScrollStateChanged(int state) { } });
这样我们就解决了 DrawerLayout 和 ViewPager 的侧滑事件冲突问题,剩下最后一个要处理的小问题就是在点击空白区域时,也想要关闭侧边栏,这个就只需要:
// 点击除开侧边栏的区域会收起侧边栏。 mDrawerLayout.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: mDrawerLayout.closeDrawers(); break; } return false; } });
到这里就大功告成啦!
作者:Hevin - 极光开发者
原文:Android 中 DrawerLayout + ViewPager 怎么解决滑动冲突?
知乎专栏:极光日报
相关文章推荐
- Android 中 DrawerLayout + ViewPager 怎么解决滑动冲突?
- Android 中 DrawerLayout + ViewPager 怎么解决滑动冲突?
- 如何解决DrawerLayout与Viewpager的滑动冲突
- Android中SwipeRefreshLayout和ViewPager左右滑动冲突的原因以及正确的解决方法
- 完美解决DrawerLayout全屏滑动及嵌套viewpager滑动冲突问题
- android 布局 使用 viewPager 时,如何解决 和 子页面 长按滑动 冲突问题
- 备忘-Android ViewPager 与Gallery滑动冲突解决方法
- MPAndroidChart在ViewPager+Fragment滑动冲突解决
- 完美解决Android里面scrollview嵌套及listview嵌套viewpager的滑动冲突问题的简单方法
- Android Listview嵌套viewpager 滑动冲突解决
- Android ScrollView嵌套ViewPager滑动失效和无法正常滑动冲突问题解决方案
- [Android] Viewpager 与 Google map v2 冲突,导致地图不能左右滑动解决
- Android中解决ListView嵌套Viewpager时,滑动事件冲突的方法
- Android listview viewpager解决冲突 滑动
- ViewPager与SwipeFreshLayout(下拉刷新)滑动冲突的解决
- Android中解决ListView嵌套Viewpager时,滑动事件冲突的方法
- 解决listview+viewpager+SwipeToRefreshLayout滑动冲突
- Android ViewPager嵌套ViewPager滑动冲突的解决方法
- Android listview viewpager解决冲突 滑动
- SwipeRefreshLayout和ViewPager滑动冲突的原因和正确的解决方式