Android滑屏与子控件点击事件处理
2015-03-23 15:55
225 查看
Android滑屏与子控件点击事件处理
想象下面画面描述中的情况,程序如何区分当前用户是想打开程序还是滑动界面?在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,完成点击事件。
/** * 是否传递到子view * true 不传递 * false 传递 * 一次触摸屏幕中,如果拦截过则不会再次进入onInterceptTouchEvent * 触摸屏幕中,如果在ACTION_DOWN时返回true,则不会再有ACTION_MOVE和ACTION_UP拦截 * 如果ACTION_DOWN返回false,ACTION_MOVE中返回true,则不会有ACTION_UP拦截 */ @Override public boolean onInterceptTouchEvent(MotionEvent event) { // TODO Auto-generated method stub switch(event.getAction()){ case MotionEvent.ACTION_DOWN: //如果ACTION_DOWN未被拦截,则有可能被子view消费,一旦消费后, //则父容器中OnTouchEvent中就不会接受到ACTION_DOWN事件 System.out.println("onInterceptTouchEvent ACTION_DOWN"); touchDownX = event.getX(); startX = this.getScrollX(); mScrolling = false; velocityTracker = VelocityTracker.obtain(); velocityTracker.addMovement(event); break; case MotionEvent.ACTION_MOVE: System.out.println("onInterceptTouchEvent ACTION_MOVE"); if(Math.abs(touchDownX - event.getX())>=mTouchSlop){ mScrolling = true; } else{ mScrolling = false; } break; case MotionEvent.ACTION_UP: //如果ACTION_MOVE判断是点击就会进入ACTION_UP,是滚动则不会进入 System.out.println("onInterceptTouchEvent ACTION_UP"); //返回false以便子控件接收ACTION_UP事件 mScrolling = false; break; } return mScrolling; } /** * onTouchEvent() 用于处理事件,返回值决定当前控件是否消费(consume)了这个事件。 * 可能你要问是否消费了又区别吗,反正我已经针对事件编写了处理代码? * 答案是有区别!比如ACTION_MOVE或者ACTION_UP发生的前提是一定曾经发生了ACTION_DOWN, * 如果你没有消费ACTION_DOWN,那么系统会认为ACTION_DOWN没有发生过, * 所以ACTION_MOVE或者ACTION_UP就不能被捕获。 * */ @Override public boolean onTouchEvent(MotionEvent event) { // TODO Auto-generated method stub switch(event.getAction()){ case MotionEvent.ACTION_DOWN: System.out.println("ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: System.out.println("ACTION_MOVE"); int offsetX = Float.valueOf(startX + touchDownX - event.getX() ).intValue(); if (offsetX>=0 && offsetX<=this.getWidth()) { scrollTo(offsetX,0); } velocityTracker.addMovement(event); break; case MotionEvent.ACTION_UP: System.out.println("ACTION_UP"); velocityTracker.computeCurrentVelocity(500); //从左往右,velocity>0,实际是想往回拔 int speed = -Float.valueOf(velocityTracker.getXVelocity()).intValue(); System.out.println("scrollX:" + this.getScrollX() + ",speed:" + speed); //开始滚动->起始点,偏移距离,持续事件 mScroller.startScroll(this.getScrollX(), 0,speed, 0,2000); velocityTracker.recycle(); break; default: break; } return true; }
相关文章推荐
- Android如何处理列表控件的item同时点击事件
- android Switch控件一直处于聚焦状态,将屏蔽Preference的点击事件(处理方式)_xp
- Android中Spinner控件关于二次点击同一item无响应事件解析及处理方法
- Android技能杂谈——如何优雅的处理控件的点击事件
- Android技能杂谈——如何优雅的处理控件的点击事件
- android之实现各个组件点击事件处理
- Android控制布局下的控件的点击事件
- design principle:模拟 android Button 控件点击事件
- android软键盘回车键的点击事件处理
- Android 系列 6.15处理长时间点击事件
- android 控件 recyvlerView添加item点击事件
- android 点击、滑动事件的处理 GestureDetector
- Android按钮的五种点击监听事件处理
- Android 控件的触摸事件传递与处理
- 安卓笔记android中控件点击事件实现的几种方式
- 安卓中控件触摸事件和点击事件的处理
- Android控件点击监听事件失效
- Android popupWindow 点击外部消失,点击外部其他控件触发其他事件
- Android 动态生成复杂的布局(View布局的子控件含自己的点击事件)
- 增加Android下spinner控件的点击下拉列表自动更新事件并实例应用--USB摄像头在spinner内下拉更新(二)