Android 中 DrawerLayout + ViewPager 怎么解决滑动冲突?
Posted 极光推送
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android 中 DrawerLayout + ViewPager 怎么解决滑动冲突?相关的知识,希望对你有一定的参考价值。
DrawerLayout 是 android 官方的侧滑菜单控件,而 ViewPager 相信大家都很熟悉了。今天这里就讲一下当在 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 事件,当滑动到最后一页时,将 DrawerLayout 的 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快速实现侧滑菜单
Android组件——使用DrawerLayout仿网易新闻v4.4侧滑菜单
Android 使用DrawerLayout快速实现侧滑菜单