zoukankan      html  css  js  c++  java
  • android 事件分发机制

     我们通过代码来分析

    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

     
  • 相关阅读:
    [SHOI2001]化工厂装箱员
    深度学习在生命科学中的应用
    亚马逊DRKG使用体验
    vue项目中使用postcss-pxtorem
    在普通的h5页面中使用stylus预处理框架
    线上服务排查命令汇总
    guava 之 Multiset/Multimap 使用总结
    ElasticSearch 基础篇 02
    guava 基础类型应用
    Guava 字符串使用总结
  • 原文地址:https://www.cnblogs.com/kebibuluan/p/7228231.html
Copyright © 2011-2022 走看看