对于这个问题,官方文档的说明很简短,想看明白很难。国外一网页说的还比较详细,写在这里分享给大家:
原文是这样的:
You receive this when a parent takes possession of the motion, for example when the user has dragged enough across a list view or scroll view that it will start scrolling instead of letting you press the buttons inside of it.
意思是这样的:
当你的手指(或者其它)移动屏幕的时候会触发这个事件,比如当你的手指在屏幕上拖动一个listView或者一个ScrollView而不是去按上面的按钮时会触发这个事件。
在设计设置页面的滑动开关时,如果不监听ACTION_CANCEL,在滑动到中间时,如果你手指上下移动,就是移动到开关控件之外,则此时会触发ACTION_CANCEL,而不是ACTION_UP,造成开关的按钮停顿在中间位置。
意思就是,当用户保持按下操作,并从你的控件转移到外层控件时,会触发ACTION_CANCEL,建议进行处理~
当前的手势被中断,不会再接收到关于它的记录。
推荐将这个事件作为 ACTION_UP 来看待,但是要区别于普通的 ACTION_UP
话说回来,平常还真碰不到这个事件,习惯上就直接当 ACTION_UP 处理了就
几乎所有的自定义控件都要手动处理onTouchEvent事件,我们知道,onTouchEvent方法返回的布尔值决定了你是否处理(消费当前事件),但是这么笼统的说其实是不准确的.准确来说,是当手指按下,也就是onTouchEvent接收到ACTION_DOWN事件的时候,如果返回true,那么就代表这次事件被我们处理,后来的ACTION_MOVE和ACTION_UP的返回结果是无所谓的. 同样的,如果在ACTION_DOWN的时候我们返回了false,那么后来的事件也不会传到这里.
ACTION_CANCLE事件如何被触发?
从表象来说明就是:当触摸事件从我们的控件开始,也就是ACTION_DOWN被我们返回true处理,然后手指移动到当前控件的外面,这时候就会触发ACTION_CANCLE事件,触发cancle事件就不会接收到up事件!!! 实际上当手指移动到了当前控件之外的时候,这个触摸事件被他的父控件拦截掉了,所以触发了cancle事件.之后的触摸事件就再也不会传递到当前控件的onTouchEvent里面.
ACTION_CANCLE事件如何处理?
关于处理,有两种办法:
1.如果是类似滑动开关,开关随着手指移动,当手指不小心移动到开关外面,我们可以对cancle进行判断,触发cancle的时候,将用户未做完的动作自动执行,也就是自动将开关滑动到左边或者右边.具体逻辑自行处理.如果你觉得这种不太好,那么请看第二种完美的解决方案.
2.类似于自定义progressBar,触发cancle的时候没法进行自动处理.其实我们可以在onTouchEvent里面先调用
requestDisallowInterceptTouchEvent(true);,这句代码的意思就是不允许父控件拦截我们的触摸事件,这样action_canlce事件就永远不会被触发.问题也就不存在了.