Android事件传递机制详解

当我们触摸某个view,这个时候就会向这个view传递一个事件,比如手指按下去这个动作,就是一个MotionEvent.ACTION_DOWN事件,手指在屏幕上移动,就是MotionEvent.ACTION_MOVE事件,手指抬起来,就是MotionEvent.ACTION_UP;
那么,如果在一个父布局中,有一个子view,两者同时设置了事件监听,当我们触摸子view时同时也触摸了父布局,那么该怎么响应呢?

这篇文章主要就讲下事件的传递机制:

首先,我们将view分为ViewGroup(容器)和子view(子控件)来讨论。

如果是一个ViewGroup,比如LinearLayout。
它具有的事件处理方法有以下四个:

1 。 public boolean dispatchTouchEvent(MotionEvent ev)

这个方法是ViewGroup独有的,我们可以理解为分发方法,也就是说,事件最开始被分发给这个ViewGroup;

2 。public boolean onInterceptTouchEvent(MotionEvent ev)

这个方法也是ViewGroup独有的,从字面意思也可以知道,它决定是否截断事件的传递,如果返回false(默认返回的也是false),则不截断,将这个事件传递给下一层的view处理。

3。 `setOnTouchListener(new OnTouchListener() {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            Log.e("ttext","父布局OnTouchListener");
            return false;
        }
    });`

网路上很多人都忽略了这个方法,这个方法其实也是事件传递中的一步,如果实现了这个接口,返回ture将截断,反之继续传递给onTouchEvent。

4 。public boolean onTouchEvent(MotionEvent event)

这个方法是ViewGroup和view都有的,可以理解为事件的处理方法,如果返回false(默认返回的也是false),那么则继续向上传递,反之直接消耗掉,不再向上传递。

全是false的情况下,传递顺序如下:
这里写图片描述

注意:

1。 dispatchTouchEvent这个方法我们一般不太关注。

2 。onInterceptTouchEvent这个方法,假如我们在手指按下MotionEvent.ACTION_DOWN的时候,就返回true,即截断往下传递的通道过后,那么,后续的move和up事件也不会再进入onInterceptTouchEvent方法,自然也不会再向下传递。只有当一个完整的手势结束(ACTION_UP)过后,才会再次进入。

3。除了系统自带的某些已经默认获取了焦点的控件,比如listview,gridview,srcrollview,button……之外,其他的类似textview,imagev这些默认是没有获得焦点的,所以必须要给它设置setOnTouchListener监听,才能响应事件。

4.特别说明一下,MotionEvent.ACTION_CANCEL这个事件,为什么说这个事件比较特别呢?
因为其他事件都对应了一个手势动作,
DOWN–按下
MOVE–移动
UP–抬起
但是CANCEL并没有对应某个动作,关于这个事件的意义,网路上很多人也说不出个所以然,只是按字面意思理解为事件的取消。

其实谷歌设置这个事件也是有对应的意义所在的,现在我们假设有这么一个场景,一个父布局里有一个带点击效果的按钮,当我们手指按下的时候,在父布局的onInterceptTouchEvent中返回false,将down这个事件传递给按钮,这个时候,按钮呈现出按下去的灰色,但是,后续的MOVE事件中我们在父布局的onInterceptTouchEvent中返回true,则事件被截断,这个时候,造成的后果就是按钮将一直呈现出按下去的灰色。
那么,这个时候就提现出CANCEL的作用了,我们可以调用event.setAction(MotionEvent.ACTION_CANCEL);将MOVE事件强制先取消掉,这个时候灰色就会被去掉了,后续的move事件则接着被父布局响应。

这个场景在下拉刷新里面,加入你是继承的listview,那么当你设置Item的点击效果时,就会出现这种情况。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值