`

【转】Android滑屏与子控件点击事件处理

 
阅读更多

转自:http://blog.csdn.net/tomatozq/article/details/44564889

想象下面画面描述中的情况,程序如何区分当前用户是想打开程序还是滑动界面?


    在android中,触摸屏幕事件逻辑如下:

1.首先调用父容器的onInterceptTouchEvent方法。

2.如果该方法返回true,则说明该触屏事件被父容器拦截,触屏事件不会传递到子控件中去处理,直接调用容器的onTouchEvent方法。

3. 如果该方法返回false,则将触屏事件传递到子控件中去处理,如果子控件在onTouchEvent方法返回true,则说明触屏事件已被消费,不会再 传递给父容器;如果子控件的onTouchEvent方法返回false,则再调用父容器的onTouchEvent处理。

4. 触屏事件一般有三个阶段ACTION_DOWN、ACTION_MOVE、ACTION_UP,在onInterceptTouchEvent方法和 onTouchEvent方法中,都可以对着三个阶段进行处理。如果父容器在onInterceptTouchEvent某一阶段返回false,则系统 会在后续阶段再次调用onInterceptTouchEvent。

    现在回到程序如何区分当前用户是想打开程序还是滑动界面的问题上,滑动界面和点击图标只有在ACTION_MOVE阶段中才能区分,子控件如果是可点击 的,则子控件的OnTouchEvent一定会返回true,也就是说如果触屏事件将ACTION_DOWN和ACTION_UP事件都传递给子控件,当 前动作就变成了点击图标,所以判断当前是滑动还是点击就必须在onInterceptTouchEvent方法中处理。

    首先在onInterceptTouchEvent的ACTION_DOWN阶段,无法判断是否滑动还是点击,则需要返回false,以便后续阶段中调用拦截事件。

    然后系统会进入onInterceptTouchEvent的ACTION_MOVE阶段,在当前阶段可以用触摸移动的距离来判断是点击还是滑动。

    判读移动距离是否大于ViewConfiguration.get(getContext()).getScaledTouchSlop(),就可以判断 是点击还是滑动,如果是点击则直接返回false,交给子控件处理;如果是滑动则返回true,然后系统就会调用容器的onTouchEvent其中 action是为ACTION_MOVE,只需要在这里处理滑动的具体代码即可。

    如果在onInterceptTouchEvent的ACTION_MOVE阶段返回true(滑动屏幕),则不会在进入 onInterceptTouchEvent的ACTION_UP阶段了,系统会直接调用onTouchEvent的ACTION_UP阶段,所以处理滑 屏的惯性效果就在这里处理。

    如果在onInterceptTouchEvent的ACTION_MOVE阶段返回false(点击图标),则系统会进入 onInterceptTouchEvent的ACTION_UP阶段,此时需要传递false,以便子控件接收ACTION_UP,完成点击事件。

 

  1. /** 
  2.  * 是否传递到子view 
  3.  * true  不传递 
  4.  * false 传递 
  5.  * 一次触摸屏幕中,如果拦截过则不会再次进入onInterceptTouchEvent 
  6.  * 触摸屏幕中,如果在ACTION_DOWN时返回true,则不会再有ACTION_MOVE和ACTION_UP拦截 
  7.  * 如果ACTION_DOWN返回false,ACTION_MOVE中返回true,则不会有ACTION_UP拦截 
  8.  */  
  9. @Override  
  10. public boolean onInterceptTouchEvent(MotionEvent event) {  
  11.     // TODO Auto-generated method stub  
  12.     switch(event.getAction()){  
  13.         case MotionEvent.ACTION_DOWN:  
  14.             //如果ACTION_DOWN未被拦截,则有可能被子view消费,一旦消费后,  
  15.             //则父容器中OnTouchEvent中就不会接受到ACTION_DOWN事件  
  16.             System.out.println("onInterceptTouchEvent ACTION_DOWN");  
  17.             touchDownX = event.getX();  
  18.             startX = this.getScrollX();  
  19.                               
  20.             mScrolling = false;  
  21.               
  22.             velocityTracker = VelocityTracker.obtain();  
  23.               
  24.             velocityTracker.addMovement(event);  
  25.             break;  
  26.         case MotionEvent.ACTION_MOVE:  
  27.             System.out.println("onInterceptTouchEvent ACTION_MOVE");  
  28.               
  29.             if(Math.abs(touchDownX - event.getX())>=mTouchSlop){  
  30.                 mScrolling = true;  
  31.             }  
  32.             else{  
  33.                 mScrolling = false;  
  34.             }  
  35.               
  36.             break;  
  37.         case MotionEvent.ACTION_UP:  
  38.             //如果ACTION_MOVE判断是点击就会进入ACTION_UP,是滚动则不会进入  
  39.             System.out.println("onInterceptTouchEvent ACTION_UP");    
  40.               
  41.             //返回false以便子控件接收ACTION_UP事件  
  42.             mScrolling = false;   
  43.               
  44.             break;  
  45.     }  
  46.       
  47.     return mScrolling;  
  48. }  
  49.   
  50. /** 
  51.  * onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。 
  52.  * 可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码? 
  53.  * 答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN, 
  54.  * 如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过, 
  55.  * 所以ACTION_MOVE或者ACTION_UP就不能被捕获。 
  56.  * */  
  57. @Override  
  58. public boolean onTouchEvent(MotionEvent event) {  
  59.     // TODO Auto-generated method stub  
  60.     switch(event.getAction()){  
  61.         case MotionEvent.ACTION_DOWN:  
  62.             System.out.println("ACTION_DOWN");                
  63.             break;  
  64.         case MotionEvent.ACTION_MOVE:  
  65.             System.out.println("ACTION_MOVE");  
  66.             int offsetX = Float.valueOf(startX + touchDownX - event.getX() ).intValue();  
  67.               
  68.             if (offsetX>=0 && offsetX<=this.getWidth()) {  
  69.                 scrollTo(offsetX,0);  
  70.             }  
  71.   
  72.             velocityTracker.addMovement(event);  
  73.               
  74.             break;  
  75.         case MotionEvent.ACTION_UP:  
  76.             System.out.println("ACTION_UP");  
  77.               
  78.             velocityTracker.computeCurrentVelocity(500);  
  79.               
  80.             //从左往右,velocity>0,实际是想往回拔  
  81.             int speed = -Float.valueOf(velocityTracker.getXVelocity()).intValue();  
  82.               
  83.             System.out.println("scrollX:" + this.getScrollX() + ",speed:" + speed);  
  84.               
  85.             //开始滚动->起始点,偏移距离,持续事件  
  86.             mScroller.startScroll(this.getScrollX(), 0,speed, 0,2000);  
  87.             velocityTracker.recycle();  
  88.             break;  
  89.         default:  
  90.             break;  
  91.     }  
  92.       
  93.     return true;  

分享到:
评论

相关推荐

    Android 滑屏控件

    网上下载的,自己略有修改和完善。懂行的人一般都会喜欢。报错的地方请注释掉即可。

    APP滑屏容器控件(Delphi)

    滑屏容器控件(FMXSliderContainer)是专为手机APP程序界面变换或图片浏览等支持滑屏操作提供的一种解决方案,该控件纯Delphi原生代码设计开发,无需其他任何第三方控件,通过该控件,能够很方便的使APP程序具有横向...

    上下滑屏控件

    上下滑屏控件 博文:http://blog.csdn.net/ethan_xue/article/details/7706248

    Android-app.rar

    Android仿微博、微信、qq 点击缩略图TransferImage Android例子源码IOS风格的uitableview列表 Android例子源码IOS风格的圆角分组设置页面 Android例子源码不断保持后台唤醒的例子源码 Android例子源码九宫格密码输入...

    Android-AndroidCustomSlideToUnlockView安卓自定义滑动解锁控件

    AndroidCustomSlideToUnlockView 安卓自定义滑动解锁控件

    android 类似UC左右滑屏 源码

    用ViewGroup 实现左右拖动,拖动到一半自动判定是否滑动完成,已经是控件形式,拿来可以直接用,在XML配置滑动个数!

    Android移动开发实例包001

    Android学习实例包,包含8个实例,是学习Android移动开发的必备利器,包含:1、Android中滑屏实现 2、ListView下拉更新功能CustomListView 3、listview下拉刷新 4、Android仿iPhone滚动控件源码 5、Android自定义...

    Android使用ViewFlipper和GestrueDetector共同实现滑屏效果实例

    主要介绍了Android使用ViewFlipper和GestrueDetector共同实现滑屏效果,结合完整实例形式分析了ViewFlipper和GestrueDetector控件实现滑屏功能的布局与相关操作技巧,需要的朋友可以参考下

    Android中ViewPager的PagerTabStrip与PagerTitleStrip用法实例

    1.ViewPager说白了就是个控件,在使用时包名要带全是Android.support.v4.view.ViewPager。由于我的ADT-Bundle版本比较高,这个包默认自带了,且默认是随apk打包导出的。如下图: 如果在Android Private Libraries里...

    iTestin使用说明

    控件识别与坐标录制脚本 支持脚本本地编辑功能 支持滑屏,长按等操作 支持账号及复杂文本的输入 支持断言、休眠、截屏等脚本操作 支持插入、删除、编辑操作 支持脚本在不同分辨率安卓终端上运行 支持脚本上传云端千款...

    Android:学习android,示例演示

    示例演示代码使用android studio书写,每个button代码一个示例SwipeRefreshLayoutpullToRefreshAChartEngine(暂未实现)Universal_Image_Loader图片的动态控制ImageSwitcherImage3...渐变透明度动画Scale:渐变尺寸缩放...

    iTestin自动化测试录制脚本工具part2

    控件识别与坐标录制脚本 支持脚本本地编辑功能 支持滑屏,长按等操作 支持账号及复杂文本的输入 支持断言、休眠、截屏等脚本操作 支持插入、删除、编辑操作 支持脚本在不同分辨率安卓终端上运行 支持脚本上传云端千款...

    iTestin自动化APP脚本录制工具part1

    控件识别与坐标录制脚本 支持脚本本地编辑功能 支持滑屏,长按等操作 支持账号及复杂文本的输入 支持断言、休眠、截屏等脚本操作 支持插入、删除、编辑操作 支持脚本在不同分辨率安卓终端上运行 支持脚本上传云端千款...

Global site tag (gtag.js) - Google Analytics