Introduction to view Basics
Slide of view
Event distribution mechanism for view
Click the Pass rule for the event
The delivery of the Click event is actually the distribution process of the Motionevent event. The distribution process of the event is mainly done by the following three methods
public boolean dispatchTouchEvent(MotionEvent ev)该方法用来进行事件的分发 如果事件能够传递到当前view 那么此方法 一定会被调用返回结果受当前view的onTouchEvent方法和下级view的dispatchTouchEvent方法的影响 表示是否能消耗当前事件public boolean onInterceptTouchEvent(MotionEvent ev)该方法在dispatchTouchEvent方法内部调用 用来判断当前view是都拦截某个事件 如果当前view拦截了某个事件那么在同一事件序列中 此方法不会被再次调用 返回结果表示是否拦截当前事件public boolean onTouchEvent(MotionEvent ev)在dispatchTouchEvent方法中调用 用来处理点击事件 返回结果表示是否消耗当前事件 如果不消耗 则在同一事件序列中当前view无法再次接受到事件上述三个方法之间的关系可以用以下伪代码来表示 public boolean dispatchTouchEvent(MotionEvent ev){ boolean consume = false; if(onInterceptTouchEvent(ev)){ consume = onTouchEvent(ev); }else{ consume = child.dispatchTouchEvent(ev); } return consume; }
For a root VIEWGROUNP, a click event will be passed to him first, and then his dispatchtouchevent will be called if the
The VIEWGROUNP Onintercepttouchevent method returns True to indicate that the VIEWGROUNP is intercepting the current event, so the current event
will be handed over to VIEWGROUNP's Ontouchevent method to handle if this VIEWGROUNP's Onintercepttouchevent method returns false
Indicates that this event is not intercepted so this event will be passed to VIEWGROUNP's child element to handle the Dispatchtouchevent method of the child element, which is called so repeatedly until the event is finally processed.
When a view needs to handle an event, if he sets the Ontouchlistener then Ontouchlistener will be called First call Ontouchlistener
The Ontouch method in this case the result of the event is to see the results of Ontouch return if Ontouch returns false then the Ontouchevent method of the view is called to handle the event when Ontouchevent handles the event If we set onclicklistener at this point, Onclicklistener will be called from here we can see that the Onclicklistener priority we often use is at the end of the event delivery mechanism.
The priority levels of these methods are as follows
Ontouchlistener–>ontouchevent–>onclicklistener
When a click event is generated, his delivery process follows the following rules
Activity–>window–>view
Events are always passed to the activity activity before being passed to the window's last window and then distributed to the top view Top view when the event is received and followed
Event distribution mechanism to distribute the event at this point if the end of view returns false in Ontouchevent then its parent container's Ontouchevent method will be called and so on if none of the elements handle the event Then the event will eventually be returned to the Ontouchevent method of activity handling activity.
will be called this process is similar to the task in the daily life of the delegation process as superior delegated subordinates to handle subordinate delegation to the lower level to deal with if the subordinate can not handle the event then the event will eventually return to the superior to handle the
About the event delivery mechanism here are some conclusions based on these conclusions, you can better understand the event delivery mechanism as shown below
The same sequence of events refers to a series of events that occur from the moment the finger is lifted to the end of the screen and ends in the middle of the line. This sequence of events starts with a down event and contains an unequal number of move events in the middle of the up event
Normally, an event sequence can only be intercepted and consumed by one view because once an element has intercepted this event, all events in the same sequence of events are handed over to that element for processing, so events in the same event sequence cannot be handed over to two view simultaneous processing but by special means A view, for example, forcibly passes an event that is supposed to be handled by ontouchevent to other view processing
Once a view intercepts an event then the sequence of events can only be handled by him and its onintercepttouchevent will not be called again because all the events in this sequence are handled by him, so there's no need to ask him if he's intercepted.
Once a view begins to process an event if he does not consume Action_down and returns false then the event will be re-handed to his parent element to process the parent element's ontouchevent will be recalled meaning that once the event is handed to a view to handle Then he's going to have to consume it at least to consume the action_down. Otherwise, the other events in the same event sequence will no longer be handed over to him. It's like the superior gives you a mission. You didn't take care of it in the first place, and then the mission didn't give you the same thing.
If the view does not consume events other than Action_down, then the click event disappears and the Ontouchevent method of the parent element is not called and the current view can continue to accept subsequent events in the sequence of events Eventually these disappearing events will be given to the activity to deal with.
VIEWGROUNP default does not intercept any events in the Android source VIEWGROUNP Onintercepttouchevent method default return to False
View no Onintercepttouchevent method event once passed to him then his ontouchevent method will be called.
The Ontouchevent method of view consumes events by default to return true unless his current state is not clickable (clickable and longclickable are false simultaneously) view longclickable default is False Clickable conditions such as a button of true TextView to False
The Enable property of the view does not affect the default return value of Ontouchevent even if a view is currently in an unavailable state, his ontouchevent method will still return true to consume the event
The onclick will occur if the current view is clickable and he receives the down and up events
The event delivery process is performed by an extrovert, where the event is always first passed to the parent element and then distributed by the parent element to the child element by requestdisallowintercepttouchevent
The Action_down method can intervene in a child element to interfere with the parent element's event distribution process to request that the parent element not intercept the event the method is invalid because reading the source indicates that the method will change
A tag bit in the parent element when the event is Acion_down, this flag bit is reset, so the method is not valid for Action_down
The sliding conflict of view
Conflict scenarios
- External slide inconsistent with internal slide direction
- The external sliding direction is consistent with the internal sliding direction
- These two cases are nested
Processing rules
- For Scenario 1, when users swipe left and right, you need to let the outside view intercept event when users swipe up and down to let the internal view intercept event What we need to do is to judge the direction of the user's slide. In particular, we can judge the direction of the user's slide according to the distance difference between the user's horizontal sliding and vertical sliding.
- For the scenario, we cannot determine which view to swipe by the user's sliding direction, so for this type of sliding conflict we need to differentiate between the two types of sliding in the business, for example, when a state requires an external view to respond to a user's swipe A different state requires an internal view to respond to the user's swipe
- For Scenario 3, a single solution to this more complex sliding conflict is definitely not going to work, so we need to combine the top two scenarios and use specific scenarios to analyze them.
How to Solve
- For scenario 1, there are two methods of external interception and internal interception for specific solutions.
External interception method
means that all click events are intercepted by the parent container (not including the down event) if the parent container needs this event to intercept if it is not necessary to intercept the external interception method, the Onintercepttouchevent method of overriding the parent container is required to make the corresponding judgment processing in the method. The general logic can
According to the following pseudo code to derive
public boolean onInterceptTouchEvent(MotionEvent ev){ boolean intercepted = false; int x = (int)ev.getX(); int y = (int)ev.getY(); switch(ev.getAction()){ case MotionEvent.ACTION_DOWN: intercepted = false; break; case MotionEvetn.ACTION_MOVE: if(父容器需要该事件){ intercepted = true; }else{ intercepted = false; } break; case MotionEvent.ACTION_UP: intercepted = false; break; default: break; } mLastXIntercept = x; mLastYIntercept = y; return intercepted; }
The above code is the typical logic of the external interception method for different sliding conflict processing only need to modify the parent container to require the current event condition can be no other need to make changes in the above code Action_down event parent container must return false because once the parent container intercepts the event Then none of the events in the back can be passed to the child element. In the Action_move event we determine whether to intercept the event as needed here is the focus of the Code ACTION_UP event we also need to return false because if we intercept the event in the parent container's move event Then the subsequent events in the sequence of events are handed over to the parent container for processing we do not need to care about the up event if we do not summarize the Intercept move event in the parent container, the event should be left to the child element to deal with, but we are here to intercept the up event, and the parent container will handle it. The child element will not be able to receive the up event then the child element will not respond correctly to the Click event so here we need to return false for the Action_up event
In summary, we just need to deal with the Action_move event. Action_down and Action_up Events we all just need to return false.
Internal interception method
The internal interception method means that the parent container does not do any logical processing during the interception phase (not the parent element does not intercept, but the default is to intercept all event sub-elements except Action_down If an event is required. You need to get the event through the Requestdisallowintercepttouchevent () method) all the interception logic processing is given to the child element to process the child element, which is consumed directly if the child element does not need the event, it is handed to the parent container to handle Compared to the external intercept method, the method compares complex pseudo-code as shown below we need to rewrite the Dispatchtouchevent method of the child element
public boolean dispatchTouchEvent(MotionEvent ev){ int x = (int) ev.getX(); int y = (int) ev.getY(); switch(MotionEvent.getAction()){ case MotionEvent.ACTION_DOWN: requestDisallowInterceptTouchEvent(true); break; case MotionEvent.ACTION_MOVE: if(子元素不需要该事件){ requestDisallowInterceptTouchEvent(false); } break; case MotionEvent.ACTION_UP: break; defalut: break; } mLastX = x; mLastY = y; return super.dispatchTouchEvent(ev); }
The code above is a typical code for internal interception. When faced with a different sliding strategy, only need to modify the child elements in the method of the judgment condition can be other places do not need to make changes in addition to the child element needs to override the method outside the parent element also needs to make some processing needs to be blocked by default except Action_down all events ( Action_down events are not controlled by the Requestdisallowtouchevent () method Once the parent container intercepts the event, then all events cannot be passed to the child element. The internal interception method is not allowed to talk about it, so when the child element thinks that no event is needed When you call Requestdisallowintercepttouchevent (FALSE), the parent container can continue to intercept after the event of the parent container is modified as follows for fixed code
public boolean onInterceptTouchEvent(MotionEvent ev){ int action = ev.getAction(); if(action == MotionEvetn.ACTION_DOWN){ return false; }else{ return true; } }
Reference: Android Development Art Exploration
Introduction to view Basics (II.)