Android自定义View—事件分发机制与滑动冲突处理(三)

View的事件分发机制,其实就是对MotionEvent事件的分发机制,即当一个MotionEvent产生了之后,系统须要把这个事件传递给一个具体的View,这个传递的过程就是分发过程。spa

一.View的事件分发机制.net

总体流程:blog

dispatchTouchEvent()—>onTouch()—>onTouchEvent()—>onClick()事件

dispatchTouchEvent():View事件分发的入口,返回值表示MotionEvent是否被消费。图片

onTouch():View须要处理事件时,若是它设置了onTouchListener,那么onTouchListener中的onTouch方法会被调用。若是onTouch方法返回false,那么View的onTouchEvent()方法会被调用;若是onTouch方法返回true,那么View的onTouchEvent()方法将不会被调用。onTouch()的优先级比onTouchEvent()的优先级更高。get

onTouchEvent():View自身对于Touch处理的实现 ,返回结果表示是否消耗当前事件。it

onClick() : View的onTouchEvent()的优先级比onClick()高,用于处理clickListener设置的点击事件。io

二.ViewGroup的事件分发机制容器

总体流程:cli

这里写图片描述

图片来自 谷歌的小弟

当一个点击事件产生之后,它的传递过程遵循以下顺序:Activity—>Window—>外层ViewGroup。 外层ViewGroup接收到事件之后,就会按照事件分发机制去分发事件。若是这个ViewGroup的onInterceptTouchEvent()方法返回true,就表示它要拦截当前事件,接着事件就会交给这个ViewGroup来处理;若是这个ViewGroup的onInterceptTouchEvent()方法返回false,就表示它不拦截当前事件,接着事件就会交给它的子元素来处理。若是一个View的onTouchEvent()返回false,那么它的父容器的onTouchEvent()就会被调用。以此类推,若是全部的元素都不处理这个事件,那么这个事件最终会传递给Activity处理,即Activity的onTouchEvent()方法会调用。

三.相关知识点

1.同一个事件序列是指从手指接触屏幕的那一刻起,到手指离开屏幕的那一刻结束,在这个过程当中所产生的一系列事件,这个事件序列以down事件开始,中间含有不定量的move事件,最终以up事件结束。

2.某个View一旦决定拦截,那么这一事件序列都只能由它来处理(若是事件序列可以传递给它的话),而且它的onInterceptTouchEvent()不会再被调用,这是由于系统会将同一事件序列内的其余方法都交给他处理。

3.某个View一旦开始处理事件,若是它不消耗ACTION_DOWN事件(onTouchEvent方法返回了false),那么同一事件序列中的其余事件都不会交给它来处理,而且事件将从新交给它的父元素处理,即父元素的onTouchEvent会被调用。

4.ViewGroup默认不拦截任何事件,即默认onInterceptTouchEvent返回false。View没有onInterceptTouchEvent方法,一旦有事件传递给它,它的 
onTouchEvent方法就会调用。

5.事件传递过程是由外向内的,即事件老是先传递给父元素,而后再由父元素分发给子View,经过requestDisallowInterceptTouchEvent方法能够在子元素中干预父元素的分发过程,可是ACTION_DOWN事件除外。

四.滑动冲突的处理

  1. 内部拦截法:子View禁止父View拦截Touch事件 
    内部拦截法是指父容器不拦截任何事件,全部的事件都传递给子元素,若是子元素须要此事件就直接消耗掉,不然就交给父容器处理。让子View调用requestDisallowInterceptTouchEvent( )禁止父View对Touch的拦截便可,这样就能够解决滑动冲突的问题。

  2. 外部拦截法:父View中准确地进行事件分发和拦截  外部拦截法是指点击事件都先通过父容器拦截处理,若是父容器须要此事件就拦截,若是不须要就不拦截。咱们能够重写父View中与Touch事件分发相关的方法—–onInterceptTouchEvent( )来进行处理,这样就能够解决滑动冲突的问题。

相关文章
相关标签/搜索