android touch事件分发机制的探究

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值