Android事件处理和传递

今天主要是讲Android的事件传递机制,在Android系统中事件传递机制分为两种,一种是ViewGroup和View两种;而修改事件传递的方向又分为两种,一种是:从ViewGroup到View的方向(这种是顺方向),另一种是从View逆修改ViewGroup的方向。本例子主要是讲解一个ViewGroup和一个View的情况。

Android系统中事件机制

区分ViewGroup和View的事件传递的区别,在ViewGroup中事件传递设计三个方法,而View只设计到两个。
  • ViewGroup涉及的三个方法
    • dispatchTouchEvent
    • onInterceptTouchEvent
    • onTouchEvent
  • View涉及的两个方法
    • dispatchTouchEvent
    • onTouchEvent
从ViewGroup到View的事件传递过程

系统中的事件传递过程
这张图是在我两年前学android的时候一个大神描述的,此图是我自己重新绘制的。有人问为什么事件传递是从Activity开始的,这里不深入了解底层,其实在Activity的onCreate方法里面setContentView方法我们把View依附给系统的Activity的时候,其实这个View依附在Activity的DecorView上面,所以这个是系统的View同样只有dispatchTouchEvent和onInterceptTouchEvent这两种方法。

 现在我们不关心Activity里面事件机制,只关心Out、Middle、Center这三个,他们现在都要三个方法,表示他们都是ViewGroup,这里我们简单的描述一下三个方法。
dispatchTouchEvent:事件分发(true:不分发,false:分发下去)
onInterceptTouchEvent:事件拦截(true:拦截,false:不拦截)
onTouchEvent:事件处理(true:处理,false:不处理)
    重点一:以上任何一个方法返回true都会表示箭头传递方向中断,用心的人会发现,假如我在dispatchTouchEvent哪里就返回为true呢?是的很多人没有考虑这个问题,假如我们在Out这个ViewGroup返回true,表示事件不会往下传递下去了,也就是说事件就在这里终止掉了,所有onTouchEvent事件我们都没法处理了。所以为什么自定义View的时候我们一般不回去处理dispatchTouchEvent这个方法。
    重点二:假若我们在onInterceptTouchEvent这个方法返回true呢?表示事件拦截掉了不会重复执行onInterceptTouchEvent这个方法了。很多人不明白什么叫不会重复执行onInterceptTouchEvent,假若你尝试返回false(Middle ViewGroup dispatchTouchEvent返回为true的时候),你会发现onInterceptTouchEvent被多次执行了。
View修改ViewGroup的事件传递方向
/**
     * 事件分发, 请求父控件是否拦截事件 
     * 1. 右划, 而且是第一个页面, 需要父控件拦截 
     * 2. 左划, 而且是最后一个页面, 需要父控件拦截
     * 3. 上下滑动, 需要父控件拦截
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
        case MotionEvent.ACTION_DOWN:
    getParent().requestDisallowInterceptTouchEvent(true);// 不要拦截,
            startX = (int) ev.getRawX();
            startY = (int) ev.getRawY();
            break;
        case MotionEvent.ACTION_MOVE:
            int endX = (int) ev.getRawX();
            int endY = (int) ev.getRawY();
    if (Math.abs(endX - startX) > Math.abs(endY - startY)) {// 左右滑动
        if (endX > startX) {// 左划
        if (getCurrentItem() == 0) {// 第一个页面, 需要父控件拦截
              getParent().requestDisallowInterceptTouchEvent(false);
            }
         } else {// 右划
               // 最后一个页面    需要拦截
               if (getCurrentItem() == getAdapter().getCount() - 1) {           getParent().requestDisallowInterceptTouchEvent(false);
            }
        }
} else {// 上下滑动
        getParent().requestDisallowInterceptTouchEvent(false);
}
break;
}
        return super.dispatchTouchEvent(ev);
}
以上是一个很典型的例子,就是在子View的dispatchTouchEvent方法里面通过getParent().requestDisallowInterceptTouchEvent这个方法就可以从子View那里修改父View的传递方向。

谢谢收看!小弟第一次写博客,以前是伸手党,若有不对的地方还请大家多多指导。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值