android touch事件分发机制的探究
来源:互联网 发布:访问php文件提示下载 编辑:程序博客网 时间:2024/05/12 02:40
android touch事件分发机制的探究
首先有个认知:
view、viewGroup、各种layout之间的关系:
viewGroup是view的子类,layout是viewGroup的子类。
自定义viewGroup必须要重写onLayout();自定义view无法重写onInterceptTouchEvent
自己做了个简单demo,用来研究touch的分发机制。先把代码贴出来:
layout文件
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/root" > <android.crm.paic.com.yueshaojun.view.Parent android:id="@+id/parent" android:layout_width="300dp" android:layout_height="400dp" android:background="#1E90FF" > <android.crm.paic.com.yueshaojun.view.ParentTwo android:layout_alignParentTop="true" android:id = "@+id/parentTwo" android:background="#FFC0CB" android:layout_width="250dp" android:layout_height="250dp"> <android.crm.paic.com.yueshaojun.view.Child android:id="@+id/child1" android:background="#8B008B" android:layout_width="100dp" android:layout_alignParentStart="true" android:layout_height="100dp"> </android.crm.paic.com.yueshaojun.view.Child> <android.crm.paic.com.yueshaojun.view.Child android:id="@+id/child2" android:background="#BA55D3" android:layout_width="100dp" android:layout_alignParentEnd="true" android:layout_height="100dp"> </android.crm.paic.com.yueshaojun.view.Child> </android.crm.paic.com.yueshaojun.view.ParentTwo> </android.crm.paic.com.yueshaojun.view.Parent></LinearLayout>
parent视图类:
package android.crm.paic.com.yueshaojun.view;import android.content.Context;import android.crm.paic.com.yueshaojun.utils.Tools;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.LinearLayout;import android.widget.RelativeLayout;/** * Created by yueshaojun on 16/7/28. */public class Parent extends RelativeLayout { public Parent(Context context, AttributeSet attrs) { super(context, attrs); } public Parent(Context context) { super(context); } public Parent(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("ondispatch","parent onTouchEvent---->"+ Tools.getView(getId())); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","parent onTouchEvent---->action_down------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","parent onTouchEvent---->action_move------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_UP: Log.i("dispatched","parent onTouchEvent---->action_up------>"+ Tools.getView(getId())); break; } return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("ondispatch","parent dispatchTouchEvent---->"+Tools.getView(getId())); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","parent dispatchTouchEvent---->action_down------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","parent dispatchTouchEvent---->action_move------>"+ ev.getRawY()+"||"+ Tools.getView(getId())); break; case MotionEvent.ACTION_UP: Log.i("dispatched","parent dispatchTouchEvent---->action_up------>"+ Tools.getView(getId())); break; } return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i("ondispatch","parent onInterceptTouchEvent---->"+Tools.getView(getId())); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","parent onInterceptTouchEvent---->action_down------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","parent onInterceptTouchEvent---->action_move------>"+ ev.getRawY()+"||"+Tools.getView(getId())); break; case MotionEvent.ACTION_UP: Log.i("dispatched","parent onInterceptTouchEvent---->action_up------>"+ Tools.getView(getId())); break; } return super.onInterceptTouchEvent(ev); }}
parentTwo(中间那层视图)
package android.crm.paic.com.yueshaojun.view;import android.content.Context;import android.crm.paic.com.yueshaojun.utils.Tools;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.LinearLayout;import android.widget.RelativeLayout;/** * Created by yueshaojun on 16/7/28. */public class ParentTwo extends RelativeLayout { public ParentTwo(Context context, AttributeSet attrs) { super(context, attrs); } public ParentTwo(Context context) { super(context); } public ParentTwo(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("ondispatch","parentTwo onTouchEvent---->"+ Tools.getView(getId())); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","parentTwo onTouchEvent---->action_down------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","parentTwo onTouchEvent---->action_move------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_UP: Log.i("dispatched","parentTwo onTouchEvent---->action_up------>"+ Tools.getView(getId())); break; } return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("ondispatch","parentTwo dispatchTouchEvent---->"+Tools.getView(getId())); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","parentTwo dispatchTouchEvent---->action_down------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","parentTwo dispatchTouchEvent---->action_move------>"+ ev.getRawY()+"||"+Tools.getView(getId())); break; case MotionEvent.ACTION_UP: Log.i("dispatched","parentTwo dispatchTouchEvent---->action_up------>"+ Tools.getView(getId())); break; } return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { Log.i("ondispatch","parentTwo onInterceptTouchEvent---->"+Tools.getView(getId())); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","parentTwo onInterceptTouchEvent---->action_down------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","parentTwo onInterceptTouchEvent---->action_move------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_UP: Log.i("dispatched","parentTwo onInterceptTouchEvent---->action_up------>"+ Tools.getView(getId())); break; } return super.onInterceptTouchEvent(ev); }}
最子视图类:
package android.crm.paic.com.yueshaojun.view;import android.content.Context;import android.crm.paic.com.yueshaojun.utils.Tools;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;/** * Created by yueshaojun on 16/7/28. */public class Child extends View { public Child(Context context) { super(context); } public Child(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("ondispatch", "child onTouchEvent---->"+ Tools.getView(getId())); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","child onTouchEvent---->action_down------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","child onTouchEvent---->action_move------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_UP: Log.i("dispatched","child onTouchEvent---->action_up------>"+ Tools.getView(getId())); break; } return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent event) { Log.i("ondispatch","child dispatchTouchEvent---->"+Tools.getView(getId())); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","child dispatchTouchEvent---->action_down------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","child dispatchTouchEvent---->action_move------>"+ Tools.getView(getId())); break; case MotionEvent.ACTION_UP: Log.i("dispatched","child dispatchTouchEvent---->action_up------>"+ Tools.getView(getId())); break; } return super.dispatchTouchEvent(event); }}
上面的代码没什么特别的,只是打了日志,方便继续看下面的内容。ondispatch标签是进到乐哪个方法中,dispatched标签是打出具体的事件。视图结构如下:
话不多说,直接从现象分析:
一、
什么都没做:
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: parent onInterceptTouchEvent—->parent
I/ondispatch: parentTwo dispatchTouchEvent—->parentTwo
I/ondispatch: parentTwo onInterceptTouchEvent—->parentTwo
I/ondispatch: child dispatchTouchEvent—->child1
I/ondispatch: child onTouchEvent—->child1
I/ondispatch: parentTwo onTouchEvent—->parentTwo
I/ondispatch: parent onTouchEvent—->parent
首先是一个调用顺序:dispatchTouchEvent——>onInterceptEvent——>onTouchEvent,
然后是父视图和子视图的调用关系:在父视图中调用dispatchTouchEvent、onInterceptTouchEvent,然后分发给子视图去调用onTouchEvent,如果子视图不处理,方向反转,依次调用父视图的onTouchEvent,直到根视图。
来个图:
这么看应该会清晰很多。由dispatchTouchEvent向下分发,onInterceptTouchEvent拦截分发,最后分发给最子视图。处于最子视图并不需要重写dispatchTouchEvent。
然而当查看具体的事件传递的情况时,日志:
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_down——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_down——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_down——>child1
I/dispatched: child onTouchEvent—->action_down——>child1
I/dispatched: parentTwo onTouchEvent—->action_down——>parentTwo
I/dispatched: parent onTouchEvent—->action_down——>parent
可以看到只有down事件,没有move、up等事件。也就是说,并不知道要交给谁处理。
于是在activity里给child添加点击事件,并且为了完整的看到事件的走向,在activity中也把dispatchTouchEvent、onTouchEvent打出日志,贴一下代码:
public class TouchActivity extends AppCompatActivity implements View.OnClickListener{ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.touch); Child child1 = (Child) findViewById(R.id.child1); Child child2 = (Child) findViewById(R.id.child2); child1.setOnClickListener(this); child2.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()){ case R.id.child1: Log.i("TouchActivity","child1"); break; case R.id.child2: Log.i("TouchActivity","child2"); break; } } @Override public boolean onTouchEvent(MotionEvent event) { Log.i("ondispatch","activity onTouchEvent---->"); switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","activity onTouchEvent---->action_down------>"); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","activity onTouchEvent---->action_move------>"); break; case MotionEvent.ACTION_UP: Log.i("dispatched","activity onTouchEvent---->action_up------>"); break; } return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.i("ondispatch","activity dispatchTouchEvent---->"); switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("dispatched","activity dispatchTouchEvent---->action_down------>"); break; case MotionEvent.ACTION_MOVE: Log.i("dispatched","activity dispatchTouchEvent---->action_move------>"); break; case MotionEvent.ACTION_UP: Log.i("dispatched","activity dispatchTouchEvent---->action_up------>"); break; } return super.dispatchTouchEvent(ev); }}
点击child1。
再来看ondispatch日志标签的内容:
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: parent onInterceptTouchEvent—->parent
I/ondispatch: parentTwo dispatchTouchEvent—->parentTwo
I/ondispatch: parentTwo onInterceptTouchEvent—->parentTwo
I/ondispatch: child dispatchTouchEvent—->child1
I/ondispatch: child onTouchEvent—->child1
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: parent onInterceptTouchEvent—->parent
I/ondispatch: parentTwo dispatchTouchEvent—->parentTwo
I/ondispatch: parentTwo onInterceptTouchEvent—->parentTwo
I/ondispatch: child dispatchTouchEvent—->child1
I/ondispatch: child onTouchEvent—->child1
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: parent onInterceptTouchEvent—->parent
I/ondispatch: parentTwo dispatchTouchEvent—->parentTwo
I/ondispatch: parentTwo onInterceptTouchEvent—->parentTwo
I/ondispatch: child dispatchTouchEvent—->child1
I/ondispatch: child onTouchEvent—->child1
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: parent onInterceptTouchEvent—->parent
I/ondispatch: parentTwo dispatchTouchEvent—->parentTwo
I/ondispatch: parentTwo onInterceptTouchEvent—->parentTwo
I/ondispatch: child dispatchTouchEvent—->child1
I/ondispatch: child onTouchEvent—->child1
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: parent onInterceptTouchEvent—->parent
I/ondispatch: parentTwo dispatchTouchEvent—->parentTwo
I/ondispatch: parentTwo onInterceptTouchEvent—->parentTwo
I/ondispatch: child dispatchTouchEvent—->child1
I/ondispatch: child onTouchEvent—->child1
dispatched日志标签的内容:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_down——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_down——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_down——>child1
I/dispatched: child onTouchEvent—->action_down——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
I/dispatched: parent onInterceptTouchEvent—->action_up——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_up——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_up——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_up——>child1
I/dispatched: child onTouchEvent—->action_up——>child1
对比上面的日志,捋一下过程:
down事件由activity的dispatchTouchEvent--》parent的dispatchTouchEvent、onInterceptTouchEvent--》parentTwo的dispatchTouchEvent、onInterceptTouchEvent--》child1的dispatchTouchEvent、onTouchEvent
然后其他事件如move、up再沿着down的路径分发,直到child1最后的onTouchEvent。
另外这说明了,事件分发的起点是activity。
二、
dispatchTouchEvent、onInterceptTouchEvent、onTouchEvent返回值有三种:true、false、super.同名方法。默认返回super.同名方法。
super.同名方法的返回情况其实就是上面试过的。
1、在parent的dispatchTouchEvent不调用super.dispatchTouchEvent依次返回true和false:
true,点击child1:
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
可以看到down、move、up都在parent的dispatchTouchEvent处理完了。没有再往下走。
false,点击child1:
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: parent dispatchTouchEvent—->parent
I/ondispatch: activity onTouchEvent—->
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: activity onTouchEvent—->
I/ondispatch: activity dispatchTouchEvent—->
I/ondispatch: activity onTouchEvent—->
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: activity onTouchEvent—->action_down——>
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: activity onTouchEvent—->action_up——>
这个有点惨,parent dispatchTouchEvent只有down事件。后面由activity的onTouchEvent接受down事件,然后move和up走activity的分发:
activity dispatchTouchEvent--》onTouchEvent
调用super.dispatchTouchEvent看看吧~
返回true,点击child1:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_down——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_down——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_down——>child1
I/dispatched: child onTouchEvent—->action_down——>child1
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
I/dispatched: parent onInterceptTouchEvent—->action_up——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_up——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_up——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_up——>child1
I/dispatched: child onTouchEvent—->action_up——>child1
事件走向:
activity dispatchTouchEvent --》parent dispatchTouchEvent、onInterceptTouchEvent--》parentTwo dispatchTouchEvent、onInterceptTouchEvent--》child dispatchTouchEvent、onTouchEvent。这个和返回super是一样的。
返回false:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_down——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_down——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_down——>child1
I/dispatched: child onTouchEvent—->action_down——>child1
I/dispatched: activity onTouchEvent—->action_down——>
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: activity onTouchEvent—->action_up——>
down事件一直传递到最底层child1,然后没人处理,又传给了activity的onTouchEvent,然后后续的事件走向:activity dispatchTouchEvent -》onTouchEvent。最后交由了activity处理。
2、在parent 的onInterceptTouchEvent 里,super点击去是默认返回false,所以返回super和false是和开始什么都没处理是一样的。
重点是返回true,那么问题来了 在down、move、up中返回true是一样的吗?打个日志看看:
在down中返回true,点击child1:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parent onTouchEvent—->action_down——>parent
I/dispatched: activity onTouchEvent—->action_down——>
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: activity onTouchEvent—->action_up——>
可以看到 在parent一层中down事件dispatchTouchEvent——》onInterceptTouchEvent--》onTouchEvent并没有往下一层parentTwo分发。然后down事件回到activity的onTouchEvent,后面事件就是由activity的dispatchTouchEvent-》onTouchEvent的正常流程。简单的说,parent的onInterceptTouchEvent 在down事件返回了true,会直接转到自己的onTouchEvent,但是后续事件自己接受不到,只能交给上一级的activity处理。
在move中返回true,点击child1;
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_down——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_down——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_down——>child1
I/dispatched: child onTouchEvent—->action_down——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onTouchEvent—->action_move——>parent
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onTouchEvent—->action_move——>parent
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onTouchEvent—->action_move——>parent
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onTouchEvent—->action_move——>parent
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
I/dispatched: parent onTouchEvent—->action_up——>parent
I/dispatched: activity onTouchEvent—->action_up——>
down事件是正常传递的,然后move事件在onInterceptTouchEvent的时候被拦截,注意这里和down事件不一样:
down事件的过程是parent dispatchTouchEvent——》onInterceptTouchEvent--》onTouchEvent,move事件没有直接到onTouchEvent,而是转到了activity的dispatchTouchEvent,再parent 的dispatchTouchEvent,接着这时候不再走parent的onInterceptTouchEvent,而是直接到了parent的onTouchEvent,再走activity的onTouchEvent,up事件也是一样。
单把parent的捞出来看
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onTouchEvent—->action_move——>parent
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
I/dispatched: parent onTouchEvent—->action_up——>parent
可以看到,move和up事件都传递到了parent的onTouchEvent,但是down事件没有,down事件最后一站在child1的onTouchEvent。而且onInterceptTouchEvent在返回了true之后不再出现。
在up事件中返回true,点击child1:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_down——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_down——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_down——>child1
I/dispatched: child onTouchEvent—->action_down——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
I/dispatched: parent onInterceptTouchEvent—->action_up——>parent
和move有些类似:down、move事件正常传递到child1的onTouchEvent就停止了。然后由activity
dispatchTouchEvent--》parent dispatchTouchEvent、onInterceptTouchEvent。parent onTouchEvent没有接受up事件,activity onTouchEvent也没有。
3、在parent 的onTouchEvent的中不调用super直接返回true、false,点击child1:
返回true:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_down——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_down——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_down——>child1
I/dispatched: child onTouchEvent—->action_down——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
I/dispatched: parent onInterceptTouchEvent—->action_up——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_up——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_up——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_up——>child1
I/dispatched: child onTouchEvent—->action_up——>child1
move的部分有些重复,但是没关系,还是能看出来,是正常的传递。
返回false:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_down——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_down——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_down——>child1
I/dispatched: child onTouchEvent—->action_down——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onInterceptTouchEvent—->action_move——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_move——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_move——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_move——>child1
I/dispatched: child onTouchEvent—->action_move——>child1
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
I/dispatched: parent onInterceptTouchEvent—->action_up——>parent
I/dispatched: parentTwo dispatchTouchEvent—->action_up——>parentTwo
I/dispatched: parentTwo onInterceptTouchEvent—->action_up——>parentTwo
I/dispatched: child dispatchTouchEvent—->action_up——>child1
I/dispatched: child onTouchEvent—->action_up——>child1
发现一样。
原因是点击child1,上面那张图的左半边是没有影响的,到child1的onTouchEvent就由child1接受了根本不会跑到parentTwo、parent的onTouchEvent。所以在parent的onTouchEvent中返回是没用的。
点击parent自己,返回true:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parent onTouchEvent—->action_down——>parent
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: parent dispatchTouchEvent—->action_move——>parent
I/dispatched: parent onTouchEvent—->action_move——>parent
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: parent dispatchTouchEvent—->action_up——>parent
I/dispatched: parent onTouchEvent—->action_up——>parent
点击parent自己,返回false:
I/dispatched: activity dispatchTouchEvent—->action_down——>
I/dispatched: parent dispatchTouchEvent—->action_down——>parent
I/dispatched: parent onInterceptTouchEvent—->action_down——>parent
I/dispatched: parent onTouchEvent—->action_down——>parent
I/dispatched: activity onTouchEvent—->action_down——>
I/dispatched: activity dispatchTouchEvent—->action_move——>
I/dispatched: activity onTouchEvent—->action_move——>
I/dispatched: activity dispatchTouchEvent—->action_up——>
I/dispatched: activity onTouchEvent—->action_up——>
可以看到parent onTouchEvent只接受到down事件。然后交由activity处理。
三、总结
1、事件传递的方向是由activity--》父视图--》子视图
2、触摸动作最终由哪个视图处理,哪个视图onTouchEvent方法接受move和up。
3、dispatchTouchEvent返回true,down、move、up都在dispatchTouchEvent中处理不会继续下发;返回false,会由上一级视图的onTouchEvent处理。
4、onInterceptTouchEvent返回true,事件会转到当前视图的onTouchEvent,但是如果拦截了down事件,onTouchEvent不会收到其他事件;拦截了move事件,down事件正常走到子视图的onTouchEvent,当前视图的onTouchEvent接受不到。
5、视图默认不处理手指动作的,除非设置了setClickable、setLongClickable、或者添加了点击或者触摸监听(本质就是setClickable、setLongClickable)。
- android touch事件分发机制的探究
- 分析Android的Touch事件分发机制
- Android Touch事件的分发响应机制
- Android View Touch的事件分发机制
- android中touch事件的分发机制
- Android事件分发机制探究
- Android Touch事件分发机制
- Android Touch事件分发机制
- android touch事件分发机制
- android Touch事件分发机制
- Android Touch事件分发机制
- Android Touch事件分发机制
- Android:Touch事件分发机制
- Android Touch事件分发机制
- Android,Touch事件分发机制。
- Android Touch事件分发机制
- Android Touch 事件分发机制
- Android:Touch事件分发机制
- 决策树(九)--极端随机森林及OpenCV源码分析
- 最简单的基于FFmpeg的编码器-纯净版(不包含libavformat)
- CSS实现span里面的字体旋转
- POJ 2065 SETI(高斯消元)
- 小白装openstack(二) 安装NTP服务
- android touch事件分发机制的探究
- SDP 协议
- UIimage的data转为NSString
- UA Curry One isn't leaked out by
- C++ 调用默认浏览器 打开指定网址
- Pornhub打不开怎么办
- 绑定127.0.0.1还是具体的ip
- node 日志管理log4js
- canvas图形变换 保存和恢复