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; } });
到这里就大功告成啦!完整的代码可以参考项目:jpush/jbox: 极光宝盒,一个基于 jpush 的轻便易用的通知框架。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: 口碑怎么砍价 口碑砍价方法
推荐阅读
-
详解Android中的NestedScrolling机制带你玩转嵌套滑动
-
html文件中jquery与velocity变量中的$冲突的解决方法
-
Android中DrawerLayout+ViewPager滑动冲突的解决方法
-
android中ListView多次刷新重复执行getView的解决方法
-
Android中实现可滑动的Tab的3种方式
-
android基础教程之android的listview与edittext冲突解决方法
-
Android中Activity滑动关闭的效果
-
Android中ImageView无法居中的问题解决方法
-
Mac中Eclipse连不上Android手机的解决方法
-
Android中判断listview是否滑动到顶部和底部的实现方法