关闭

Android事件分发的View的焦点捕捉事件

标签: android
184人阅读 评论(0) 收藏 举报
分类:
事件分发的View的焦点捕捉事件:
ScrollView里面嵌套ListView(不需要时隐藏这个布局), 可以解决滑动问题. 就是滑动到ListView的时候, ScrollView也跟着滑动,这样子联动的效果比较好.
如果是ScrollView里面是一个Fragment,然后Fragment里面是一个ListView, 这样子就无法做到ScrollView和ListView联动的效果了,因为基于事件分发原理,一个焦点只能由一个View捕获,如果不禁止父容器的捕获事件的能力,那么这个嵌套在Fragment的ListView将无法捕获屏幕按下去的这个事件,所以这个ListView在你没有做特殊处理之前是不能滑动的. 你要禁止了父容器捕获事件这个api,然后+ListView才可以滑动,不过有缺点就是ListView和ScrollView不能一起联动.
具体实现的Api如下,要在设置onTouchListener监听的时候, 根据情况对ACTION_UP或者ACTION_DOWN进行单独设置.
listview.setOnTouchListener(new View.OnTouchListener()){
@Override
public boolean onTouch(View v, MotionEvent event){
if(event.getAction == MotionEvent.ACTION_UP)){
v.getParent().requestDisallowInterceptTouchEvent(false);
}else{
v.getParent().requestDisallowInterceptTouchEvent(true); // 屏蔽父容器的拦截事件
}
return false;
}
}

简介:
一个Activity或View的onTouchEvent()回调函数会接收到touch事件(就是这个setOnTouchListener).
调用的时候这两个方法也只是先后顺序的问题.先调用setOnTouchListener(),这个方法里面要你重写onTouch(), 而且调用了onTouch()方法会先于onTouchEvent(). 并且一旦设置了onTouchListener并且最后onTouch()方法返回了true,那么onTouchEvent()就不再被执行,(先执行setOnTouchListener里的onTouch()方法, 再执行onTouchEvent() ) 如果setOnTouchListener的onTouch()方法返回的是false,onTouchEvent()就会继续被调用.

onClickListener和onTouchEvent有些关系, onTouchEvent默认实现是会调用onClickListener里面的onClick()方法,如果重写了onTouchEvent,因为onClickListener接收不到ACTION_DOWN和ACTION_UP,那么再设置onClickListener也就不会再生效了,这时候单击或者长按处理只能在onTouchEvent中自己处理了.


关于事件传递的机制,这里给出一些结论,根据这些结论可以更好地理解整个传递机制,如下所示:
(1)同一个事件序列是指从手指接触屏幕的那一刻起, 到手指离开屏幕的那一刻结束,在这个过程所产生的一系列事件,这个事件序列以down开始,中间含有数量不定的move事件,最终以up事件结束.

(2)正常情况下,一个事件序列只能被一个View拦截且消耗.这一条原因可以参考(3), 因为一旦一个元素拦截了某此事件,那么同一个事件序列内的所有事件都会直接交给它处理,因此同一个事件序列中的事件不能分别由两个View同时处理, 但是通过特殊手段可以做到, 比如一个View本该将自己处理的事件通过onTouchEvent强行传递给其他View做到.

(3)某个View一旦决定拦截,那么这一事件序列只能由它来处理(如果事件序列能够传递给它的话), 并且它的onInterceptTouchEvent不会再被调用. 这条也很好理解, 就是说当一个View决定拦截一个事件后, 那么系统会把同一个事件序列内的其他方法都直接交给它处理, 因此就不用再调用这个View的onInterceptTouchEvent()来询问它是否要被拦截了.

(4)某个View一旦开始处理事件, 如果它不消耗ACTION_DOWN事件(onTouchEvent返回了false), 那么同一个事件序列中的其他事件都不会交给它处理,并且事件会重新交给到它的父元素去处理, 即父元素的onTouchEvent()会被调用. 意思就是事件一旦交给一个View处理,那么后续的一系列move,up事件都会在这个View中被处理,

(5)如果View不消耗ACTION_DOWN以外的其他事件,那么这个点击事件会消失,此时父元素的onTouchEvent并不会被调用,并且当前View可以持续收到后续的事件,最终这些消失的点击事件会传递给Activity处理.

(6)ViewGroup默认不拦截任何事件,Android源码的ViewGroup的onInteceptTouchEvent方法默认返回false.

(7)View没有onInterceptTouchEvent方法, 一旦有点击事件传递给它, 那么它的onTouchEvent方法就会被调用.

(8)( Button之所以比较特殊是因为它的clickable为true, 所以Button的onTouchEvent()会返回true, 默认设置为消耗事件. )View的onTouchEvent默认都会消耗事件(返回true), 除非它是不可点击的( clickable和longClickable同时为false ). View的longClickable的属性默认为false, clickable属性要分情况, 比如Button和clickable属性默认为true, 而TextView的clickable属性默认为false.

(9) View的enable属性不影响onTouchEvent的默认返回值. 哪怕一个View是disable状态的, 只要它的clickable或者longClickable有一个为true, 那么它的onTouchEvent就返回true.

onClick()是会对ACTION_DOWN和ACTION_UP两个动作同时发生才作响应.
(10) onClick()会发生的前提是当前View是可点击(enable = true)的, 并且它收到了down和up的事件.

(11) 事件的传递过程是由外向内的, 即事件总是先传递给父元素, 然后再由父元素分发给子View, 通过requestDisallowInterceptTouchEvent方法可以在子元素中干预父元素的事件分发过程, 但是ACTION_DOWN事件除外.



一个完整的手势(事件序列)是
一个完整的事件序列以Down开始, 中间包含若干个Move, 然后以Up结束.
setOnClickListener的优先级是最低的,
官方提供的GestureDetector(手势检测辅助类)给我们提供了可能。
class SimpleGestureListener implements GestureDetector.OnGestureListener { @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { return false; // 猛扔 }}
通过这个类,我们可以很方便的处理除了单击和长按之外,还有滑动,双击等各种手势,并对其分别进行处理,如果这些还是不能满足你的好奇心,那还有一个官方提供的ScaleGestureDetector,从名字就可以判断出来这是一个检测缩放手势的辅助类
private void init() { scaleGesture = new ScaleGestureDetector(getContext(), new ScaleListener()); moveGesture = new MoveGestureDetector(getContext(), new MovingListener()); rotateGesture = new RotateGestureDetector(getContext(), new RotateListener()); } @Override public boolean onTouchEvent(MotionEvent event) { scaleGesture.onTouchEvent(event); moveGesture.onTouchEvent(event); rotateGesture.onTouchEvent(event); return true; } private class ScaleListener implements ScaleGestureDetector.OnScaleGestureListener { @Override public boolean onScale(ScaleGestureDetector detector) { setScaleX(detector.getScaleFactor() * getScaleX()); setScaleY(detector.getScaleFactor() * getScaleY()); return true; } @Override public boolean onScaleBegin(ScaleGestureDetector detector) { return true; } @Override public void onScaleEnd(ScaleGestureDetector detector) { } }


0
0
查看评论

Android View 事件分发机制源码详解(View篇)

Android View事件分发机制源码解析
  • a553181867
  • a553181867
  • 2016-05-02 14:31
  • 5270

Android焦点事件分发与传递机制

Android 焦点事件分发与传递机制
  • zhcswlp0625
  • zhcswlp0625
  • 2017-04-05 20:45
  • 4606

Android6.0 ViewGroup/View 事件分发机制详解

以Android6.0的源码为基础,分析一下Android系统的ViewGroup/View Touch事件的分发机制
  • meiliwanghan
  • meiliwanghan
  • 2016-06-03 16:40
  • 4520

【自定义View系列】View的事件分发机制

本部分介绍View的一个核心知识点:事件分发机制。事件分发机制不仅仅是核心知识点更是难点,不少初学者甚至中级开发者面对这个问题都会觉得困惑。另外,View的另一大难题滑动冲突,它的解决方法的理论基础就是事件分发机制,因此掌握好View的事件分发机制是十分重要的。为什么需要事件分发机制http://b...
  • a910626
  • a910626
  • 2016-06-01 09:41
  • 1145

Android事件分发与焦点争夺

问题引出:ListView 的 Item 有Button等可点击控件的时候,Button设置了onClickListener后,上层的Item能不能接收到点击事件?ViewGroup包含子View时,存在焦点争夺,默认情况下,子view中含有可点击控件时(Button)会获取到焦点, ViewGro...
  • tobevan
  • tobevan
  • 2016-07-18 09:34
  • 1399

Android事件分发、View事件Listener全解析

  • zhongkejingwang
  • zhongkejingwang
  • 2014-07-26 11:12
  • 4435

图解android焦点传递,事件分发

能用图示bi
  • quanjin24k
  • quanjin24k
  • 2014-04-09 12:13
  • 1834

Android的视图绘制与事件分发流程(底层)

本文我们来简单的分析下Activity的SetContentView方法底层是如何对我们的layout.xml文件进行处理,然后分析一下事件是如何从WindowManagerService中传递到View的dispatchTouchEvent方法中的,最后会简单了解下PhoneWindow、Deco...
  • evan_man
  • evan_man
  • 2016-08-13 15:26
  • 1038

Android View 事件分发机制 源码解析 (上)

一直想写事件分发机制的文章,不管咋样,也得自己研究下事件分发的源码,写出心得~首先我们先写个简单的例子来测试View的事件转发的流程~1、案例为了更好的研究View的事件转发,我们自定以一个MyButton继承Button,然后把跟事件传播有关的方法进行复写,然后添加上日志~MyButtonpack...
  • lmj623565791
  • lmj623565791
  • 2014-09-02 09:32
  • 62686

View的事件分发机制(Activity篇)

这篇博客主要介绍在一个TouchEvent从Activity传递到View的流程,照例附上一张流程图:我们的TouchEvent首先接收到这个TouchEvent的是Acitivty中的dispatchTouchEvent(MotionEvent ev)方法,这个方法里面第19行是将这个Touch事...
  • freedom13905149949
  • freedom13905149949
  • 2016-07-21 17:42
  • 1283
    个人资料
    • 访问:1452次
    • 积分:102
    • 等级:
    • 排名:千里之外
    • 原创:9篇
    • 转载:0篇
    • 译文:0篇
    • 评论:2条
    文章分类
    文章存档