当前位置: 移动技术网 > IT编程>移动开发>Android > Android中DrawerLayout+ViewPager滑动冲突的解决方法

Android中DrawerLayout+ViewPager滑动冲突的解决方法

2019年07月24日  | 移动技术网IT编程  | 我要评论

银湖汽车站订票电话,让生命充满爱完整版,太阳帝国的原罪汉化补丁

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 的轻便易用的通知框架

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持移动技术网。

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网