1. 程式人生 > >android 事件分發機制

android 事件分發機制

cnblogs instance 1.0 必須 div called tool per 測試環境

技術分享

技術分享

技術分享

我們通過代碼來分析

package im.weiyuan.com.viewutils;

import android.content.Intent;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView; import android.widget.Toast; public class MainActivity extends AppCompatActivity { private MyView view; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); view
= (MyView) findViewById(R.id.view_main); /** * 設置touch監聽事件 * */ view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) {
Log.d("123456","MyView setOnTouchListener is called ");
return false; } }); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { Log.d("123456","activity dispatchTouchEvent is called" +ev.getAction()); return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { Log.d("123456","activity onTouchEvent is called"+event.getAction()); return super.onTouchEvent(event); } }

package im.weiyuan.com.viewutils;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

/**
 * Created by wei.yuan on 2017/7/24.
 */

public class MyView  extends ImageView {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d("123456","MyView dispatchTouchEvent is called"+event.getAction());
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("123456","MyView onTouchEvent is called"+event.getAction());
        return super.onTouchEvent(event);
    }
}

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="im.weiyuan.com.viewutils.MainActivity">



    <im.weiyuan.com.viewutils.MyView
        android:text="點擊"
        android:src="@mipmap/ic_launcher"
        android:id="@+id/view_main"
        android:layout_width="100dp"
        android:layout_height="100dp" />
</LinearLayout>

我們來進行下面的測試環境的操作:
1、點擊activity的頁面,不點擊圖片,只點擊activity

07-24 11:29:59.882 16649-16649/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called0
07-24 11:29:59.882 16649-16649/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called0
07-24 11:29:59.889 16649-16649/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:29:59.889 16649-16649/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called2
07-24 11:29:59.911 16649-16649/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:29:59.911 16649-16649/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called2
07-24 11:29:59.930 16649-16649/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:29:59.930 16649-16649/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called2
07-24 11:29:59.937 16649-16649/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:29:59.938 16649-16649/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called2
07-24 11:29:59.938 16649-16649/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called1
07-24 11:29:59.938 16649-16649/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called1

日誌的打印上面所示:

首先調用activity dispatchTouchEvent is called0 0表示手指按下 2表示手指移動,1表示手指擡起

dispatchTouchEvent會調用對應的activity的dispatchTouchEvent來分發事件

onTouchEvent 用來處理分發的事件

2、下面我們來進行下面的操作,我們點擊圖片,我們來看看日誌打印

07-24 11:39:22.171 28610-28610/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called0
07-24 11:39:22.172 28610-28610/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called0
07-24 11:39:22.172 28610-28610/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:39:22.173 28610-28610/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called0
07-24 11:39:22.174 28610-28610/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called0
07-24 11:39:22.185 28610-28610/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:39:22.185 28610-28610/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called2
07-24 11:39:22.220 28610-28610/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:39:22.220 28610-28610/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called2
07-24 11:39:22.228 28610-28610/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:39:22.228 28610-28610/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called2
07-24 11:39:22.229 28610-28610/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called1
07-24 11:39:22.229 28610-28610/im.weiyuan.com.viewutils D/123456: activity onTouchEvent is called1

首先是activity去分發事件,將事件分發給圖片,圖片沒有孩子,不會再繼續分發事件,這個時候取調用圖片的回調方法TouchListen,然後調用MyView onTouchEvent去消費事件,

因為MyView onTouchEvent函數的返回值不是true,沒有消費給事件,如果返回值是true,事件就被消費了,事件必須要有消費者,所以只能又把事件讓給activity去處理,所以接下來調用了activity的: activity onTouchEvent is called0

後面調用了activity的 2 就是move事件,這裏默認事件不再分發給圖片處理了,為啥了,因為分發給圖片的down 事件都沒有消費,所以move事件就不會在分發給圖片處理了

我們來驗證下,我們把代碼返回值設置成true

package im.weiyuan.com.viewutils;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

/**
 * Created by wei.yuan on 2017/7/24.
 */

public class MyView  extends ImageView {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d("123456","MyView dispatchTouchEvent is called"+event.getAction());
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("123456","MyView onTouchEvent is called"+event.getAction());
        return true;
    }
}

07-24 11:47:41.893 2667-2667/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called0
07-24 11:47:41.894 2667-2667/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called0
07-24 11:47:41.894 2667-2667/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:47:41.895 2667-2667/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called0
07-24 11:47:41.919 2667-2667/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:47:41.919 2667-2667/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called2
07-24 11:47:41.919 2667-2667/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:47:41.919 2667-2667/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called2
07-24 11:47:41.925 2667-2667/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called1
07-24 11:47:41.926 2667-2667/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called1
07-24 11:47:41.926 2667-2667/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:47:41.926 2667-2667/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called1

activity將時間分發給圖片去處理,不管是down事件還是move事件,消費者都是圖片

接下來做下面的事情,將圖片的touch回調事件的返回值設置成true

package im.weiyuan.com.viewutils;

import android.content.Intent;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;



public class MainActivity extends AppCompatActivity {

    private MyView view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        view = (MyView) findViewById(R.id.view_main);
        /**
         * 設置touch監聽事件
         * */
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.d("123456","MyView setOnTouchListener is called ");
                return true;
            }
        });

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("123456","activity dispatchTouchEvent is called" +ev.getAction());
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("123456","activity onTouchEvent  is called"+event.getAction());
        return super.onTouchEvent(event);
    }
}

package im.weiyuan.com.viewutils;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

/**
 * Created by wei.yuan on 2017/7/24.
 */

public class MyView  extends ImageView {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d("123456","MyView dispatchTouchEvent is called"+event.getAction());
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("123456","MyView onTouchEvent is called"+event.getAction());
        return true;
    }
}

 我們來看下日誌的打印:



07-24 11:51:23.555 9263-9263/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called0
07-24 11:51:23.556 9263-9263/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called0
07-24 11:51:23.556 9263-9263/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:51:23.591 9263-9263/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:51:23.591 9263-9263/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called2
07-24 11:51:23.591 9263-9263/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:51:23.592 9263-9263/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called1
07-24 11:51:23.592 9263-9263/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called1
07-24 11:51:23.592 9263-9263/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called

我們來分析下,這個時候activity將事件分發給圖片,因為圖片的回調函數返回值是true,默認是回調函數對事件進行了消費了,所以這個時候就不會在調用圖片的onTouchEvent消費事件了,事件的消費都有回調函數來進行處理了,一個事件只能被消費一次,

如果事件不被視圖消費,最終由activity消費

我們來在做下面的修改

package im.weiyuan.com.viewutils;

import android.content.Intent;
import android.os.PersistableBundle;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;



public class MainActivity extends AppCompatActivity {

    private MyView view;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        view = (MyView) findViewById(R.id.view_main);
        /**
         * 設置touch監聽事件
         * */
        view.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                Log.d("123456","MyView setOnTouchListener is called ");
                if(event.getAction() == MotionEvent.ACTION_DOWN){
                    return  true;
                }
                return false;
            }
        });

    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.d("123456","activity dispatchTouchEvent is called" +ev.getAction());
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("123456","activity onTouchEvent  is called"+event.getAction());
        return super.onTouchEvent(event);
    }
}

package im.weiyuan.com.viewutils;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

/**
 * Created by wei.yuan on 2017/7/24.
 */

public class MyView  extends ImageView {
    public MyView(Context context) {
        super(context);
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public MyView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.d("123456","MyView dispatchTouchEvent is called"+event.getAction());
        return super.dispatchTouchEvent(event);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.d("123456","MyView onTouchEvent is called"+event.getAction());
        return true;
    }
}

 我們來看看日誌的打印:

07-24 11:58:28.653 16280-16280/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called0
07-24 11:58:28.654 16280-16280/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called0
07-24 11:58:28.654 16280-16280/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:58:28.657 16280-16280/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:58:28.657 16280-16280/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called2
07-24 11:58:28.658 16280-16280/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:58:28.658 16280-16280/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called2
07-24 11:58:28.674 16280-16280/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:58:28.674 16280-16280/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called2
07-24 11:58:28.674 16280-16280/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:58:28.674 16280-16280/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called2
07-24 11:58:28.690 16280-16280/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:58:28.691 16280-16280/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called2
07-24 11:58:28.691 16280-16280/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:58:28.691 16280-16280/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called2
07-24 11:58:28.757 16280-16280/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called2
07-24 11:58:28.758 16280-16280/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called2
07-24 11:58:28.758 16280-16280/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:58:28.758 16280-16280/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called2
07-24 11:58:28.758 16280-16280/im.weiyuan.com.viewutils D/123456: activity dispatchTouchEvent is called1
07-24 11:58:28.758 16280-16280/im.weiyuan.com.viewutils D/123456: MyView dispatchTouchEvent is called1
07-24 11:58:28.758 16280-16280/im.weiyuan.com.viewutils D/123456: MyView setOnTouchListener is called
07-24 11:58:28.758 16280-16280/im.weiyuan.com.viewutils D/123456: MyView onTouchEvent is called1

 

android 事件分發機制