前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android触屏事件流[通俗易懂]

Android触屏事件流[通俗易懂]

作者头像
全栈程序员站长
发布2022-09-30 19:39:22
1.2K0
发布2022-09-30 19:39:22
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

一次触屏事件分为三个动作

ACTION_DOWN, ACTION_MOVE 和 ACTION_UP。

其中ACTION_DOWN和ACTION_UP在一次触屏事件中只会触发一次,ACTION_MOVE可能触发任意次(包括0次)。

主要响应触屏的组件有两种,一种是可以包含子元素的(ViewGroup比如LinearLayout),另一种是不能包含子元素的View(最底层的View比如Button)。

当一个触屏事件产生时,正两者的响应方法有一个主要的区别就是LinearLayout有onInterceptTouchEvent方法,而Button没有onInterceptTouchEvent方法。

1

ViewGroup(比如LinearLayout)

2

boolean dispatchTouchEvent(MotionEvent event)

3

boolean onInterceptTouchEvent(MotionEvent event)

4

boolean onTouchEvent(MotionEvent event)

5

6

View(比如Button)

7

boolean dispatchTouchEvent(MotionEvent event)

8

boolean onTouchEvent(MotionEvent event)

总的来说,dispatchTouchEvent决定处理什么,onInterceptTouchEvent决定谁来处理,onTouchEvent决定怎么处理。所以对于Button来谁,没有小弟,自然不存在决定谁来处理的问题,故没有onInterceptTouchEvent方法

下面具体说一下这三个函数的主要作用:

dispatchTouchEvent决定处理什么,看名字就知道是事件分发,初看我还以为是分发到子元素呢,原来不是直接到子元素。其实更好的理解是这是一个过滤方法。此方法的主要作用是决定相应事件的类型。

假如dispatchTouchEvent返回false,那么在响应了ACTION_DOWN之后,后续的ACTION_MOVE和ACTION_UP均忽略,因此ACTION_MOVE和ACTION_UP永远不会有得到处理的机会。

假如dispatchTouchEvent,那么后续的ACTION_MOVE和ACTION_UP均被接受,可以被其他方法响应。

特别注意,如果在这一步的dispatchTouchEvent中没有调用super.dispatchTouchEvent(event),那么事件就到此为止,被终结了。此时此刻只有dispatchTouchEvent会响应事件,另外两个方法根本没有机会来响应事件。并且,事件不会传递到子元素中。

onInterceptTouchEvent,主要决定谁来处理(即是否拦截事件)。只要在dispatchTouchEvent中调用了super.dispatchTouchEvent(event)那么,事件(event)会被交给onInterceptTouchEvent去处理。注意,这里事件(event)是否会调用onInterceptTouchEvent与dispatchTouchEvent的返回值是true还是false无关。再次强调,dispatchTouchEvent只决定处理什么,并不能指定谁来调用。

假如onInterceptTouchEvent返回false,将事件(event)交自己的子元素处理(此时事件流是从外到内,从父元素到子元素)。

假如onInterceptTouchEvent返回true,将事件(event)交给自己的onTouchEvent来处理,并且如果有后续的ACTION_MOVE和ACTION_UP(前一步dispatchTouchEvent中返回true)的话,将不再调用onInterceptTouchEvent,直接将事件传递给自己的onTouchEvent来处理。

注意上一步,在onInterceptTouchEvent返回true的情况下,onTouchEvent将获得事件并进行具体的处理。

假如onTouchEvent返回false,将事件(event)交父元素处理,(注意在这一步,事件流反向了,此时事件流是从内到外,从子元素到父元素)。

假如onTouchEvent返回true,本次事件(event)就到此为止,被终结了。

对照上面的说法,下面给出实例说明:

01

public class MyLinearLayout1 extends LinearLayout{

02

03

private String TAG = "第一层MyLinearLayout";

04

05

public MyLinearLayout1(Context context) {

06

super(context);

07

this.setBackgroundColor(Color.WHITE);

08

}

09

public void setTagString(String tag){

10

TAG = tag;

11

}

12

13

@Override

14

public boolean dispatchTouchEvent(MotionEvent event){

15

if(MotionEvent.ACTION_DOWN == event.getAction()){

16

Log.v(TAG + "dispatchTouchEvent:", "ACTION_DOWN");

17

}else if(MotionEvent.ACTION_MOVE == event.getAction()){

18

Log.v(TAG + "dispatchTouchEvent:", "ACTION_MOVE");

19

}else{

20

Log.v(TAG + "dispatchTouchEvent:", "ACTION_UP");

21

}

22

<span style="color:#e53333;">//super.dispatchTouchEvent(event);</span> return true;

23

}

24

25

@Override

26

public boolean onInterceptTouchEvent(MotionEvent event){ super.onInterceptTouchEvent

27

28

if(MotionEvent.ACTION_DOWN == event.getAction()){

29

Log.v(TAG + "onInterceptTouchEvent:", "ACTION_DOWN");

30

}else if(MotionEvent.ACTION_MOVE == event.getAction()){

31

Log.v(TAG + "onInterceptTouchEvent:", "ACTION_MOVE");

32

}else{

33

Log.v(TAG + "onInterceptTouchEvent:", "ACTION_UP");

34

}

35

return true;

36

}

37

38

@Override

39

public boolean onTouchEvent(MotionEvent event){ super.onTouchEvent(event)

40

if(MotionEvent.ACTION_DOWN == event.getAction()){

41

Log.v(TAG + "onTouchEvent:", "ACTION_DOWN");

42

}else if(MotionEvent.ACTION_MOVE == event.getAction()){

43

Log.v(TAG + "onTouchEvent:", "ACTION_MOVE");

44

}else{

45

Log.v(TAG + "onTouchEvent:", "ACTION_UP");

46

}

47

48

return true;

49

}

50

}

此时没有调用super.dispatchTouchEvent(event),所以事件没有机会得到其他的处理。

打印信息:

1

第一层MyLinearLayoutdispatchTouchEvent:(460): ACTION_DOWN

2

第一层MyLinearLayoutdispatchTouchEvent:(460): ACTION_UP

如果将上面boolean dispatchTouchEvent(MotionEvent event)的返回值修改为false,那么按照前面说的,MyLinearLayout1在响应了ACTION_DOWN之后,不会再响应本次触屏操作的其他事件。所以此时的打印结果是:

1

第一层MyLinearLayoutdispatchTouchEvent:(460): ACTION_DOWN

可以看到,ACTION_UP没有被响应,因为本事件被忽略了。

现在,将super.dispatchTouchEvent(event)的注释去掉,注意,现在的boolean dispatchTouchEvent(MotionEvent event)变成下面这样:

01

@Override

02

public boolean dispatchTouchEvent(MotionEvent event){

03

if(MotionEvent.ACTION_DOWN == event.getAction()){

04

Log.v(TAG + "dispatchTouchEvent:", "ACTION_DOWN");

05

}else if(MotionEvent.ACTION_MOVE == event.getAction()){

06

Log.v(TAG + "dispatchTouchEvent:", "ACTION_MOVE");

07

}else{

08

Log.v(TAG + "dispatchTouchEvent:", "ACTION_UP");

09

}<p> <span style="color:#e53333;">super.dispatchTouchEvent(event);//去掉注释了</span></p>

10

<p> return true;</p>

11

}

打印信息:

1

第一层MyLinearLayout ACTION_DOWN:(783): ACTION_DOWN

2

第一层MyLinearLayout onInterceptTouchEvent:(783): ACTION_DOWN

3

第一层MyLinearLayout onTouchEvent:(783): ACTION_DOWN

4

第一层MyLinearLayout dispatchTouchEvent:(783): ACTION_UP

5

第一层MyLinearLayout onTouchEvent:(783): ACTION_UP

具体顺序为下:

1

ACTION_DOWN:ACTION_DOWN——>onInterceptTouchEvent——>onTouchEvent

2

ACTION_UP:ACTION_DOWN——>onTouchEvent

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/195353.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月10日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档