全网整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:400-708-3566

Android滑动事件冲突的解决方法

滑动是Android中不可缺少的一部分,多个滑动必然会产生冲突,比如我们最常见的是ScrollView中嵌套了ListView,一般做法是计算出ListView的总高度,这样就不用去滑动ListView了。又比如一个ViewPager嵌套Fragment,Fragment里面又有ListView,这原本是有滑动冲突的,但是ViewPager内部去帮我们解决了这种冲突。那如果我们要自己解决冲突又该怎么办呢。

下面有两种方式来解决:

外部拦截法
外部拦截法是指在有点击事件时都要经过父容器,那么在父容器时如果需要拦截就拦截自己处理,不需要则传递给下一层进行处理,下面看个例子:

首先定义一个水平滑动的HorizontalScrollViewEx,看主要代码

主要的拦截是需要重写onInterceptTouchEvent

@Override 
 public boolean onInterceptTouchEvent(MotionEvent ev) { 
 boolean intercepted = false; 
 int x = (int) ev.getX(); 
 int y = (int) ev.getY(); 
 switch (ev.getAction()) { 
 case MotionEvent.ACTION_DOWN: 
 //down事件不拦截,否则无法传给子元素 
 intercepted = false; 
 if (!mScroller.isFinished()) { 
  mScroller.abortAnimation(); 
  intercepted = true; 
 } 
 break; 
 case MotionEvent.ACTION_MOVE: 
 int deltaX = x - mLastXIntercept; 
 int deltaY = y - mLastYIntercept; 
 //水平滑动则拦截 
 if (Math.abs(deltaX) > Math.abs(deltaY) + 5) { 
  intercepted = true; 
 } else { 
  intercepted = false; 
 } 
 break; 
 case MotionEvent.ACTION_UP: 
 //不拦截,否则子元素无法收到 
 intercepted = false; 
 break; 
 } 
 //因为当ViewGroup中的子View可能消耗了down事件,在onTouchEvent无法获取, 
 // 无法对mLastX赋初值,所以在这里赋值一次 
 mLastX = x; 
 mLastY = y; 
 mLastYIntercept = y; 
 mLastXIntercept = x; 
 return intercepted; 
 } 

在down事件不需要拦截,返回false,否则的话子view无法收到事件,将全部会由父容器处理,这不是希望的;up事件也要返回false,否则最后子view收不到。

看看move事件,当水平滑动距离大于竖直距离时,代表水平滑动,返回true,由父类来进行处理,否则交由子view处理。这里move事件就是主要的拦截条件判断,如果你遇到的不是水平和竖直的条件这么简单,就可以在这里进行改变,比如,ScrollView嵌套了ListView,条件就变成,当ListView滑动到底部或顶部时,返回true,交由父类滑动处理,否则自身ListView滑动。

在onTouchEvent中主要是做的滑动切换的处理

@Override 
 public boolean onTouchEvent(MotionEvent event) { 
 mVelocityTracker.addMovement(event); 
 int x = (int) event.getX(); 
 int y = (int) event.getY(); 
 switch (event.getAction()) { 
 case MotionEvent.ACTION_DOWN: 
 if (!mScroller.isFinished()) { 
  mScroller.abortAnimation(); 
 } 
 break; 
 case MotionEvent.ACTION_MOVE: 
 int deltaX = x - mLastX; 
 int deltaY = y - mLastY; 
 if (getScrollX() < 0) { 
  scrollTo(0, 0); 
 } 
 scrollBy(-deltaX, 0); 
 break; 
 case MotionEvent.ACTION_UP: 
 int scrollX = getScrollX(); 
 mVelocityTracker.computeCurrentVelocity(1000); 
 float xVelocityTracker = mVelocityTracker.getXVelocity(); 
 if (Math.abs(xVelocityTracker) > 50) {//速度大于50则滑动到下一个 
  mChildIndex = xVelocityTracker > 0 ? mChildIndex - 1 : mChildIndex + 1; 
 } else { 
  mChildIndex = (scrollX + mChildWith / 2) / mChildWith; 
 } 
 mChildIndex = Math.max(0, Math.min(mChildIndex, mChildrenSize - 1)); 
 int dx = mChildIndex * mChildWith - scrollX; 
 smoothScrollBy(dx, 0); 
 mVelocityTracker.clear(); 
 break; 
 } 
 mLastY = y; 
 mLastX = x; 
 return true; 
 } 

在这个嵌套一个普通的ListView,这样就可以解决水平和竖直滑动冲突的问题了。

<com.example.lzy.customview.HorizontalScrollViewEx 
 android:layout_width="match_parent" 
 android:layout_height="200dp"> 
 
 <ListView 
 android:id="@+id/listView" 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" /> 
 
 <Button 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:background="@android:color/holo_blue_bright" 
 android:text="2" /> 
 
 <Button 
 android:layout_width="match_parent" 
 android:layout_height="match_parent" 
 android:background="@android:color/holo_green_dark" 
 android:text="3" /> 
 </com.example.lzy.customview.HorizontalScrollViewEx> 

其他的部分代码如果需要可以下载源码来看

内部拦截法

内部拦截法是父容器不拦截任何事件,所有事件都传递给子view,如果需要就直接消耗掉,不需要再传给父容器处理

下面重写一个ListView,只需要重写一个dispatchTouchEvent方法就OK

public class ListViewEx extends ListView { 
 
 private static final String TAG = "lzy"; 
 private int mLastX; 
 private int mLastY; 
 
 public ListViewEx(Context context) { 
 super(context); 
 } 
 
 public ListViewEx(Context context, AttributeSet attrs) { 
 super(context, attrs); 
 } 
 
 public ListViewEx(Context context, AttributeSet attrs, int defStyleAttr) { 
 super(context, attrs, defStyleAttr); 
 } 
 
 
 @Override 
 public boolean dispatchTouchEvent(MotionEvent ev) { 
 int x = (int) ev.getX(); 
 int y = (int) ev.getY(); 
 
 switch (ev.getAction()) { 
 case MotionEvent.ACTION_DOWN: 
 //子View的所有父ViewGroup都会跳过onInterceptTouchEvent的回调 
 getParent().requestDisallowInterceptTouchEvent(true); 
 break; 
 case MotionEvent.ACTION_MOVE: 
 int deltaX = x - mLastX; 
 int deltaY = y - mLastY; 
 if (Math.abs(deltaX) > Math.abs(deltaY) + 5) {//水平滑动,使得父类可以执行onInterceptTouchEvent 
  getParent().requestDisallowInterceptTouchEvent(false); 
 } 
 break; 
 } 
 mLastX = x; 
 mLastY = y; 
 return super.dispatchTouchEvent(ev); 
 } 
} 

在down事件调用getParent().requestDisallowInterceptTouchEvent(true),这句代码的意思是使这个view的父容器都会跳过onInterceptTouchEvent,在move中判断如果是水平滑动就由父容器去处理,父容器只需要把之前的onInterceptTouchEvent改为下面那样,其他不变。

@Override 
 public boolean onInterceptTouchEvent(MotionEvent ev) { 
 int x = (int) ev.getX(); 
 int y = (int) ev.getY(); 
 if (ev.getAction() == MotionEvent.ACTION_DOWN) { 
 mLastX = x; 
 mLastY = y; 
 if (!mScroller.isFinished()) { 
 mScroller.abortAnimation(); 
 return true; 
 } 
 return false; 
 } else { 
 //如果是非down事件,说明子View并没有拦截父类的onInterceptTouchEvent 
 //说明该事件交由父类处理,所以不需要再传递给子类,返回true 
 return true; 
 } 
 } 

最终实现效果就是下面那样,两个是用两种方式实现的,上面的圆圈是一个简单的自定义View练习

下载地址:Android滑动事件冲突

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


# Android滑动事件冲突  # Android滑动冲突  # Android滑动事件  # Android中实现监听ScrollView滑动事件  # Android编程之滑动按钮事件实例详解  # Android ListView监听滑动事件的方法(详解)  # 重写  # 不需  # 在这里  # 跳过  # 要再  # 就可以  # 的是  # 是一个  # 如果你  # 在这个  # 是有  # 都要  # 多个  # 子类  # 也要  # 下载地址  # 不需要  # 是指  # 水平和  # 两种 


相关文章: 装修招标网站设计制作流程,装修招标流程?  新网站制作渠道有哪些,跪求一个无线渠道比较强的小说网站,我要发表小说?  如何用狗爹虚拟主机快速搭建网站?  简单实现Android验证码  广州顶尖建站服务:企业官网建设与SEO优化一体化方案  极客网站有哪些,DoNews、36氪、爱范儿、虎嗅、雷锋网、极客公园这些互联网媒体网站有什么差异?  香港服务器租用费用高吗?如何避免常见误区?  建站之星如何实现网站加密操作?  如何规划企业建站流程的关键步骤?  如何通过服务器快速搭建网站?完整步骤解析  高防网站服务器:DDoS防御与BGP线路的AI智能防护方案  专业网站制作企业网站,如何制作一个企业网站,建设网站的基本步骤有哪些?  外汇网站制作流程,如何在工商银行网站上做外汇买卖?  如何快速搭建高效可靠的建站解决方案?  山东网站制作公司有哪些,山东大源集团官网?  网站广告牌制作方法,街上的广告牌,横幅,用PS还是其他软件做的?  网站制作和推广的区别,想自己建立一个网站做推广,有什么快捷方法马上做好一个网站?  学校为何禁止电信移动建设网站?  c# 在高并发下使用反射发射(Reflection.Emit)的性能  Swift中循环语句中的转移语句 break 和 continue  如何选择高效便捷的WAP商城建站系统?  详解ASP.NET 生成二维码实例(采用ThoughtWorks.QRCode和QrCode.Net两种方式)  如何在Windows 2008云服务器安全搭建网站?  如何获取开源自助建站系统免费下载链接?  山东云建站价格为何差异显著?  建站主机无法访问?如何排查域名与服务器问题  枣阳网站制作,阳新火车站打的到仙岛湖多少钱?  如何批量查询域名的建站时间记录?  网页设计与网站制作内容,怎样注册网站?  如何快速搭建响应式可视化网站?  如何获取免费开源的自助建站系统源码?  长沙企业网站制作哪家好,长沙水业集团官方网站?  如何高效利用亚马逊云主机搭建企业网站?  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  文字头像制作网站推荐软件,醒图能自动配文字吗?  打鱼网站制作软件,波克捕鱼官方号怎么注册?  简历在线制作网站免费版,如何创建个人简历?  C#如何在一个XML文件中查找并替换文本内容  建站之星后台管理如何实现高效配置?  如何快速生成凡客建站的专业级图册?  手机网站制作平台,手机靓号代理商怎么制作属于自己的手机靓号网站?  临沂网站制作公司有哪些,临沂第四中学官网?  如何快速登录WAP自助建站平台?  建站之星在线版空间:自助建站+智能模板一键生成方案  行程制作网站有哪些,第三方机票电子行程单怎么开?  如何用AWS免费套餐快速搭建高效网站?  深圳 网站制作,深圳招聘网站哪个比较好一点啊?  建站之星后台密码遗忘或太弱?如何重置与强化?  实例解析angularjs的filter过滤器  建站之星会员如何解锁更多建站功能? 

您的项目需求

*请认真填写需求信息,我们会在24小时内与您取得联系。