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)。

0 0
原创粉丝点击