Android event distribution mechanism for conflict resolution and slide

Excerpt:  https://www.jianshu.com/p/d82f426ba8f7

Bowen write better, retained them for easy viewing

 

In Androiddevelopment, the event distribution mechanism is an Android more important knowledge, become familiar with the entire distribution mechanism contributes to better analyze failures and click on the slide to slide conflict, better to extend the control functions and development of events custom controls, and event distribution mechanism is the Android interview will ask one of the test sites, sum up by saying: event distribution mechanism is very important.

Android event distribution process

Internet blog about the event distribution mechanism of a lot, but many are written and posted about a Demo or take the output of the Log source code analysis, and then a bunch of notes and illustrations, the reader may be difficult to read, or to read later, right again before long forgotten. Well, today I used a diagram to sum up the whole process Android event distribution mechanism, if you can leave this picture in mind, remember that the entire process of distribution mechanisms, go read those source blog will be more impressed by it! Anyway, I was impressed very deeply! Well, see Figure! (Since remember this picture, my mother no longer have to worry about my child by the interviewer it!)

 
Event distribution mechanism U-shaped Fig.

Comment:

  • 1. The entire flow chart is divided into three layers: Activity, ViewGroup, View, i.e. the simplest case.
  • 2. The entire event from the Activitybeginning, by the Activity of dispatchTouchEventdoing the distribution.
  • 3. The dashed line represents the characters on this return value, into false, true, super.
  • 4. Currently the figure is for all the events ACTION_DOWN, and for ACTION_MOVEand ACTION_UPwe separately analyzed.
  • 5.View is no onInterceptTouchEventmethod, this is easy to understand, because not passed down, so there is no saying whether the interception of the event.

In conjunction with the entire chart, we have come to a few conclusions to the event stream (I hope the reader to concentrate on the comparison of the U-shaped diagram to remember these conclusions, Duokanjibian, the brain has a relatively clear concept.)

  • Case return value super.xxx (): The Conclusion: 1 implementation of the default event is the return value super.xxx (), that is, we do not have to rewrite or change the return value of the controls inside the method, but directly with super the default implementation calls the parent class, then the whole event should flow from Activity ----> ViewGroup ---> View from the top down dispatchTouchEvent method call, time until the leaf node (View), and then from the View --- > ViewGroup ---> Activity invoked from the bottom up onTouchEventmethod. If the time ViewGroup will pass downwardly to pass then to the lower onInterceptTouchEvent dispatchTouchEvent, the flow of the entire event is a U-shaped type in FIG.

  • Conclusion 2: The return value is false case: For dispatchTouchEvent and onTouchEvent, in addition to Activity false return value of the event on behalf of their own consumption, ViewGroup and View the event will be back to the parent control onTouchEvent to deal with. The onInterceptTouchEvent returns false when representatives not to intercept the default event is not blocked, and when it returns a value of super.xxx () is the same, the event will continue to be passed to the underlying dispatchTouchEvent to deal with.

  • Conclusion 3: Return the case is true: For dispatchTouchEvent and onTouchEvent for both Activity, or ViewGroup View returns true and represents itself to consume the event, no longer passed down. For onInterceptTouchEvent, the return value is true representatives of intercepting passes the event, since the interception, on behalf of not passed down, and this time it will be passed to the event itself onTouchEvent to deal with.

The three above conclusion on behalf of all the events ACTION_DOWN event of transfer possibilities do not know readers against U-flow diagram, is there a clear understanding of it in mind. Believe remember these three conclusions, to go along with the source code to understand, to distribute more events have a better understanding of it! OK, we continue to look at is how ACTION_UP ACTION_MOVE and passed it!

Note: The above explanation is for ACTION_DOWN events, ACTION_MOVE and ACTION_UP and ACTION_DOWN not the same as in the delivery process, you ACTION_DOWN in the implementation of returns false, (case: ACTION_DOWN return value false, the return value is not dispatchTouchEvent is false) behind a series of other action will not get executed. Simply put, it is when dispatchTouchEvent distributed during the event, and only return to the previous event (such as ACTION_DOWN) true, will receive ACTION_MOVE and ACTION_UP events.

The above mentioned, if the event is not to be interrupted, then will continue to spread down the leaf layer (View), then continue back to the Activity, dispatchTouchEvent and onTouchEvent can return true consumer event, the end of event delivery, and while onInterceptTouchEvent not consume the event, which is equivalent to a fork in acts of diversion diversion, and ACTION_UP ACTION_MOVE in which the function is called, said before the function which was not received ACTION_DOWN, will receive subsequent events ACTION_MOVE etc. . (Due to the consumption event, only ACTION_DOWN and ACTION_MOVE occur, and therefore only consider the situation returns a value of true)

For ACTION_UP ACTION_MOVE and different transfer functions, the following conclusions:

  • Conclusion 1: For dispatchTouchEvent: The return value is true, the event their own consumption. Because the return value is true representatives of the consumer, the event is not propagated to the following, so here ACTION_DOWN events to stop the transfer, ACTION_MOVE and ACTION_UP also passed to stop here passed down, this time passing direction is the same.

  • Conclusion 2: For onTouchEvent: the return value is true, their own consumption events. Because the events to onTouchEvent there may be lower or View ViewGroup return over this time ACTION_DOWN is passed through the lower back, but this time ACTION_MOVE and ACTION_UP and will not be passed to the lower; there may be a true return to their onInterceptTouchEvent transfer over, this time ACTION_MOVE and delivery processes ACTION_UP and ACTION_DOWN events is the same.

For ACTION_MOVE, ACTION_UP ultimate summary:
ACTION_DOWN events which control the consumption (return true), then ACTION_MOVE and ACTION_UP will be from top to bottom (by dispatchTouchEvent) do pass down event distribution, this control will only spread, not We will continue to pass down, if the event is ACTION_DOWN consumption in dispatchTouchEvent, then the event so far to stop the transfer, if the event is onTouchEvent ACTION_DOWN consumption, then the event will ACTION_MOVE or ACTION_UP pass onTouchEvent process control and end the transfer.

Slide conflict resolution

Introduced over the basic process event distribution mechanism, we look at slide conflict. The basic form of conflict is divided into two sliding, sliding other complex conflict can be split into two basic forms:

  • 1: External sliding direction inconsistent with an internal direction.
  • 2: outer direction coincides with the direction of the interior.

A first first look inconsistent sliding direction of the case. For example, such as you use ViewPaper and Fragment with, and often Fragment in a vertical sliding ListView this case will have a sliding conflict, but because ViewPaper itself has been handled well slide conflict, so we need to consider, however, if this happened ScrollView, we have to deal with their own sliding conflict. Illustrated as follows:

 
Where the sliding direction inconsistency

Look at the second, in this case, because the same internal and external sliding direction, the system will tell you which part of the slide, it will be only one layer can either slide or slide together two very Caton. Illustrated as follows:

 
Where the sliding direction of the same

In both cases, we have different ways to deal with it.

The first: a first main collision is a horizontal, a vertical, so long as the development of our judgment sliding direction is vertical or horizontal, let the corresponding View swipe. There are many methods of determination, such as comparison with the lateral distance from the vertical size, which is determined to a large distance in the direction in which the slide; like angle formed with the horizontal slide path.

The second: In this case, rather special, we do not have general rule, you have to draw the appropriate processing rules based on business logic. For a simple example, the pull-down refresh ListView, ListView need to achieve their slide to slide, but need to slide together when the sliding head and ListView Header, which is to slide the entire parent container, which involves sliding the conflict, If you do not handle the slide conflict, there will be all kinds of unexpected situations. For the resolution of the situation, we can use the intercept method:

  • 1. External intercept method (transmission event is determined by the parent vessel): Let the events are processed through the interception of the parent container (onInterceptTouchEvent), if the parent is required to intercept the container, if not not to intercept, it referred to as external intercept method, the pseudo code show as below:
 
External intercept method

Code comments:

a: First down event of the parent container must return false, because if it returns true, which is intercepted down event, and subsequent move up events are passed on to the parent container (onTouchEvent), there is no opportunity to deal with sub-elements of the event.

b:其次是up事件也返回了false,一是因为up事件对父容器没什么意义,其次是因为若事件是子元素处理的,却没有收到up事件会让子元素的onClick事件无法触发。

  • 2:内部拦截法(自己决定事件的传递):父容器不拦截任何事件,将所有事件传递给子元素,如果子元素需要则消耗掉,如果不需要则通过requestDisallowInterceptTouchEvent方法(请求父类不要拦截,返回值为true时不拦截,返回值为false时为拦截)交给父容器处理,称为内部拦截法,使用起来稍显麻烦,伪代码如下:

首先我们需要重写子元素的dispatchTouchEvent方法:

 
dispatchTouchEvent方法

然后修改父容器的onInterceptTouchEvent方法:

 
父容器的onInterceptTouchEvent方法

滑动冲突解决实战

    1. 滑动方向不一致的情况:

看代码看不出所以然,我们通过实例来看看滑动冲突是怎么样的。我们先模拟第一种场景,内外滑动方向不一致,我们先自定义一个父控件,让其可以左右滑动,类似于ViewPaper:

 
内外滑动方向不一致

然后在布局中添加listview

 
添加listview之后的界面

可以看到左右滑动确实失效了,说明确实产生了滑动冲突。那么我们就来解决一下吧!首先我们要明白滑动规则是什么,这个例子中如果我们竖直滑动就让ListView消耗事件进行滑动,水平滑动就让我们自定义的父容器滑动。

首先用外部拦截法,我们需要重写onInterceptTouchEvent方法,代码如下:

 
外部拦截法

这里我们判断横向滑动的距离与竖直滑动距离的长短。若是竖直滑动的长,则判断为竖直滑动,那么就是ListView的滑动,就将intercepted置为false,让父容器不拦截,交由子元素ListView处理。若是横向,则intercepted置为true,交由父容器处理。OK,完美解决滑动冲突问题,效果图:

 
最终效果图

接下来看看内部拦截法:重写其dispatchTouchEvent方法:

 
dispatchTouchEvent方法

再重写外部父容器的oninterceptTouchEvent方法:

 
父容器的oninterceptTouchEvent方法
  • 2.滑动方向一致的情况:

接下来看看同方向的滑动冲突,这里我们用一个竖直的ScrollView嵌套一个ListView做例子。首先看看没有解决滑动冲突的时候是咋样的:

 
滑动方向一致的情况

我们看到只要ScrollView可以滑动,内部的ListView是不能滑动的。那我们现在来解决这个问题,同向滑动冲突和与不同向滑动冲突不一样,得根据实际的需求来确定拦截的规则。

这里我们的需求是当ListView滑到顶部了,并且继续向下滑就让ScrollView拦截掉;当ListView滑到底部了,并且继续向下滑,就让ScrollView拦截掉,其余时候都交给ListView自身处理事件。

首先用外部拦截法,我们需要重写ScrollView的onInterceptTouchEvent方法,代码如下:

 
外部拦截法

这里我们看到Down事件里我们并没有返回false而是返回super.onInterceptTouchEvent(event),这是因为ScrollView在Down方法时需要初始化一些参数如果我们直接返回false,会导致滑动出现问题。并且前面说过ViewGroup的onInterceptTouchEvent方法是默认返回false的,所以我们这里要返回super方法才可。OK,完美解决,效果图就不贴出来了,你懂的。

接下来看看内部拦截法:先重写ScrollView的onInterceptTouchEvent方法,让其拦截除了Down事件以外的其他方法:

 
父容器的onInterceptTouchEvent方法

在重写ListView的dispatchTouchEvent方法,规则已经说明过了:

 
listview的dispatchTouchEvent方法

效果图:

 
最终效果图

最终实现了完美解决滑动冲突。解决问题的感觉是不是特别爽呢! <{=....(嘎嘎嘎~)

好了,这篇文章到此结束,希望各位读者看完之后能对事件分发机制有更深入的了解,在实际项目开发中,遇到滑动冲突问题时能够轻松解决问题,喜欢的话点个赞吧。(#.#)

 
 
作者:Android_Jieyao

链接:https://www.jianshu.com/p/d82f426ba8f7
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

Guess you like

Origin www.cnblogs.com/qinaidexin/p/11720318.html