Android事件分发机制学习笔记

Android事件分发机制学习笔记

今天刚接触Android的事件分发机制,参考网上的资料,而且又正好买了人生中第一款正版桌面应用——MindNode2。所以就用它来制作了一个Android事件分发的思维导图。
接下来且听我细细道来:
代码是参考网上他人博客的,转载地址:Android事件分发和消费机制
先来看看布局文件:

<?xml version="1.0" encoding="utf-8"?>
<cn.sunzn.tevent.TouchEventFather xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="#468AD7"
    android:gravity="center"
    android:orientation="vertical" >

    <cn.sunzn.tevent.TouchEventChilds
        android:id="@+id/childs"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:background="#E1110D"
        android:text="@string/hello" />

</cn.sunzn.tevent.TouchEventFather>

接下来看一下Activity:Activity重写了dispathchTouchEvent和onTouchEvent两个方法。Activity是顶层,也是第一个出发事件的。

package cn.sunzn.tevent;

import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;

public class TouchEventActivity extends Activity {

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.w("sunzn", "TouchEventActivity | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));
        return super.dispatchTouchEvent(ev);
    }

    public boolean onTouchEvent(MotionEvent event) {
        Log.w("sunzn", "TouchEventActivity | onTouchEvent --> " + TouchEventUtil.getTouchAction(event.getAction()));
        return super.onTouchEvent(event);
    }

然后我们自定义View分别是:TouchEventFather、TouchEventChilds。两个类分别继承了LinearLayout
TouchEventFather类是最外层的View

package cn.sunzn.tevent;

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

public class TouchEventFather extends LinearLayout {

    public TouchEventFather(Context context) {
        super(context);
    }

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

    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.e("sunzn", "TouchEventFather | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));
        return super.dispatchTouchEvent(ev);
    }

    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.i("sunzn", "TouchEventFather | onInterceptTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));
        return super.onInterceptTouchEvent(ev);
    }

    public boolean onTouchEvent(MotionEvent ev) {
        Log.d("sunzn", "TouchEventFather | onTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));
        return super.onTouchEvent(ev);
    }

}

TouchEventChilds是里面的View

    package cn.sunzn.tevent;
    import android.content.Context;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.widget.LinearLayout;

    public class TouchEventChilds extends LinearLayout {

       public TouchEventChilds(Context context) {
            super(context);
        }

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

     public boolean dispatchTouchEvent(MotionEvent ev) {
            Log.e("sunzn", "TouchEventChilds | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));
            return super.dispatchTouchEvent(ev);
        }

       public boolean onInterceptTouchEvent(MotionEvent ev) {
            Log.i("sunzn", "TouchEventChilds | onInterceptTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));
            return super.onInterceptTouchEvent(ev);
        }

        public boolean onTouchEvent(MotionEvent ev) {
            Log.d("sunzn", "TouchEventChilds | onTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));
            return super.onTouchEvent(ev);
        }

}

接下来就是一个工具类,主要用于方便调试,很简单。

package cn.sunzn.tevent;

import android.view.MotionEvent;

public class TouchEventUtil {

    public static String getTouchAction(int actionId) {
        String actionName = "Unknow:id=" + actionId;
        switch (actionId) {
        case MotionEvent.ACTION_DOWN:
            actionName = "ACTION_DOWN";
            break;
        case MotionEvent.ACTION_MOVE:
            actionName = "ACTION_MOVE";
            break;
        case MotionEvent.ACTION_UP:
            actionName = "ACTION_UP";
            break;
        case MotionEvent.ACTION_CANCEL:
            actionName = "ACTION_CANCEL";
            break;
        case MotionEvent.ACTION_OUTSIDE:
            actionName = "ACTION_OUTSIDE";
            break;
        }
        return actionName;
    }

}

下面这个就是我制作的Android分发机制的导图,解释下:

我们可以看到每个类中都有dispatchTouchEvent和onInterceptTouchEvent、onTouchEvent。这是因为他们都来自于View,但是只有Activity没有onInterceptTouchEvent是因为其他两个类是继承LinearLayout,而LinearLayout又继承ViewGroup,ViewGroup继承View。而在Activity中没有onInterceptTouchEvent这个接口。

从Activity开始触发分发方法
首先是dispathchTouchEvent判断是否在本类中消费,返回true表示在dispathchTouchEvent中消费,但是为什么会调用onTouchEvent呢?我们来看看源码,感觉被骗了…
下边的就是Activity中的dispathchTouchEvent,看哪个if,如果事件被分发就返回true,但是现在事件没有被任何地方分发,所以进入了onTouchEvent方法中,这个方法有个if,不用管它,注释里有一句说The default implement ation always returns false所以dispathchTouchEvent还是返回了false。
所以在Activity中dispathchTouchEvent不管返回什么,都会进入onTouchEvent这个方法中。


这里写图片描述


  • 在TouchEventFather中的dispathchTouchEvent为true的情况下,表示由自己消费不向下传递。
    返回false表示不分发触摸事件,但触摸事件来自TouchEventActivity,便返回上一层的onTouchEvent进行消费。
  • 再来看看onInterceptTouchEvent,返回true表示拦截不会向下传递,先传递给自己的onTouchEvent处理,如果未做处理则继续向上到Activity中的onTouchEvents处理。
    如果返回false,表示不进行拦截,继续向下分发事件。

    好了最后一个TouchEventChilds和上面一样,不需要在多说什么了,只有一点,最下层的View中onInterceptTouchEvent返回什么都一样,因为没有可以拦截的事件了。
    还有一点需要说明的是,在onTouchEvent中如果返回false,表示未进行消费,冒泡到上一层直到Activity,如果返回true表示消费事件不会在向上冒泡,super也是一样。
    这里写图片描述查看大图

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值