Explain the distribution, interception, and execution of Android events _android

Source: Internet
Author: User

In normal development, we often encounter events such as clicking, sliding, and so on. Sometimes there are all kinds of sliding conflicts between different view. For example, both inside and outside the layout can be sliding, then there will be conflicts. This is when we need to know about the Android event distribution mechanism.
The Android Touch event distribution process is done in three important ways: Dispatchtouchevent, Onintercepttouchevent, Ontouchevent. Let me give a general introduction to these three methods.

Public boolean dispatchtouchevent (motionevent ev)

Used for distribution of events. If the event can be passed to the current view, the method is bound to be invoked, and the result is affected by the ontouchevent of the current view and the Dispatchtouchevent method of the subordinate view, indicating whether the current event is consumed. Action_down dispatchtouchevent () returns True, and subsequent events (Action_move, action_up) are passed again if False,dispatchtouchevent () is returned Can not receive action_up, Action_move. Simply put, when Dispatchtouchevent is in the event distribution, only the previous action returns True, the latter action is triggered.

Public boolean onintercepttouchevent (Motionevent event)

This method is invoked in the Dispatchtouchevent method to intercept an event. If the current view intercepts an event, in the same sequence of events, this method is not invoked again, and the result returned indicates whether the current event is blocked. It is the method provided by the ViewGroup and returns false by default.

public boolean ontouchevent (Motionevent event)

Called in the Dispatchtouchevent method to handle the Click event, the return result indicates whether the current event is consumed (true indicates consumption, false indicates no consumption), and if not consumed, the current view cannot receive the event again in the same sequence of events. Both view and ViewGroup have this method, and the view defaults to return true, indicating that the event was consumed.

In view, there are two callback functions:

public boolean dispatchtouchevent (Motionevent ev);
public boolean ontouchevent (Motionevent ev);

In ViewGroup, there are three callback functions:

public boolean dispatchtouchevent (Motionevent ev);
public boolean onintercepttouchevent (Motionevent ev);
public boolean ontouchevent (Motionevent ev);

What are the differences and relationships between the above three methods? This is indicated by a pseudo code:

public boolean dispatchtouchevent (motionevent ev) { 
 Boolean consume = false; 
 if (onintercepttouchevent (EV)) { 
  consume = ontouchevent (EV); 
 } else { 
  consume = child.dispatchtouchevent ( EV); 
 } 
 return consume; 
} 

Through the above pseudocode, you may have a clearer understanding of the rules of the Click event, namely: for a root viewgroup, the Click event is generated, the first pass to it, then its dispatchtouchevent will be called, If this ViewGroup Onintercepttouchevent method returns true indicating that it wants to intercept this event, then this event will be given to the viewgroup processing, that is, its Ontouchevent method will be invoked If this ViewGroup Onintercepttouchevent method returns false, it means that it does not intercept this event, which is the child element that the current event will continue to pass to it, and then the Dispatchtouchevent method of the child element is invoked. So repeatedly until the event is finally dealt with.

The following pictures refer to [EoE]:

• Figure one: Action_down are not consumed

• Figure II (a): Action_down was consumed by the view


• Figure II (II): Subsequent action_move and up will be looking for view without being intercepted


• Figure III: The follow-up is intercepted.


• Figure IV: Action_down was intercepted at the outset

View event Distribution Source Analysis:
Dispatchtouchevent Method:

public boolean dispatchtouchevent (Motionevent event) { 
 if montouchlistener!= null && (Mviewflags & Enab Led_mask = = ENABLED && Montouchlistener.ontouch (this, event)) {return 
  true; 
 } 
 Return Ontouchevent (event); 
}

If Montouchlistener!= null, (Mviewflags&enabled_mask) ==enabled and Montouchlistener.ontouch (this, event) all three conditions are true, Returns True, otherwise the Ontouchevent (event) method is executed and returned.

To sum up, Ontouch can be executed with two prerequisites (all satisfied):
1. Set the Ontouchlistener
2. Control is the Enable state

And ontouchevent can be executed to meet any one of the following three conditions:
1. No set Ontouchlistener
2. The control is not a enable state
3.onTouch return False

Let's take a look at the return value of Dispatchtouchevent, which is actually controlled by the return value of the Ontouch and ontouchevent functions, which means that the touch event returns true for successful consumption, and it returns true, indicating that the distribution was successful, The sequence of events thereafter is also distributed here, and if false, the distribution fails, and the sequence of events thereafter is no longer distributed.
Ontouchevent Method:

 if ((viewflags & clickable) = = Clickable | | (ViewFlags & long_clickable) = = long_clickable)) {
  ...
  return true;
 }

The ontouchevent of the view consumes the event by default (this method returns True) unless it is not clickable (clickable and longclickable are false). and view's longclickable defaults to false,clickable attributes, such as button defaults to True,textview, ImageView defaults to False.

public boolean PerformClick () { 
 sendaccessibilityevent (accessibilityevent.type_view_clicked); 
 if (Monclicklistener!= null) { 
  playsoundeffect (soundeffectconstants.click); 
  Monclicklistener.onclick (this); 
  return true; 
 } 
 return false; 
}

This is not the familiar onclicklistener, it used to be called in the ontouchevent. As long as Monclicklistener is not NULL, it will call its OnClick method.

The conclusion that the onclick can be executed requires two prerequisites (all satisfied):
1. Can be implemented to ontouchevent
2. Set the Onclicklistener

The event forwarding process for the entire view is:
Dispatchevent->setontouchlistener->ontouchevent->setonclicklistener

Finally, there is a question, Setonlongclicklistener and Setonclicklistener can only execute one?
A: No, as long as the onclick in Setonlongclicklistener returns FALSE, two will execute, and return true will block Setonclicklistener.

ViewGroup Event Distribution Source Analysis:
Dispatchtouchevent Method:

Two kinds of possible entry into the if snippet (that is, the event is distributed to the child view):
1, currently do not allow interception, that is disallowintercept = true.
2, no interception currently, that is, onintercepttouchevent (EV) return FALSE.

Note: Disallowintercept is the ability to disable event interception, which is false by default and can be set by Viewgroup.requestdisallowintercepttouchevent (Boolean) , and onintercepttouchevent (EV) can make a replication.

After entering the if code snippet, through a For loop, iterate through all the child views under the current ViewGroup to determine if the currently traversed view is a view that is being clicked, and if so, call the view's dispatchtouchevent. I went into the view of the event distribution process, which is said. Is mmotiontarget=child when child.dispatchtouchevent (EV) returns true; Indicates that the Dispatchtouchevent return value of ViewGroup is affected by the Childview dispatchtouchevent return value, the child view event is distributed successfully, and ViewGroup event distribution is successful. The sequence of events that follows will also be distributed here (from the above knowing that clickable or longclickable of the child view can distribute successfully), and if ViewGroup event distribution fails or No child view is found (click on a blank position), Will go to its ontouchevent, the future sequence of events will not be distributed down, go directly to ontouchevent.

The entire ViewGroup event forwarding process is:
Dispatchevent->onintercepttouchevent->child.dispatchevent-> (setontouchlistener->ontouchevent)

The above summary is based on: if there is no interception, then how to intercept it?
onintercepttouchevent

 public boolean onintercepttouchevent (Motionevent ev) {return 
 false; 
}

The code is very simple, only one sentence, that is, return false,viewgroup default is not intercepted. If you need to intercept, just return true, so that the event is not passed to the child view, and if you return true at down, Down,move,up view will not catch the event; The child view will not catch the event in move and up.

How to not be intercepted:
if ViewGroup's onintercepttouchevent (EV) is return True when Action_move, the move of the child view is blocked and the up event When the child view wants to still be able to respond to move and up?
A: Onintercepttouchevent is defined in ViewGroup, the child view cannot be modified. Android provides us with a method: Requestdisallowintercepttouchevent (Boolean) is used to set whether interception is allowed, as we write directly in the dispatchtouchevent of the Child view:

 @Override Public 
  Boolean dispatchtouchevent (Motionevent event) 
  { 
   getparent (). Requestdisallowintercepttouchevent (true); 
   int action = Event.getaction ();  
   Switch (action) {case 
   Motionevent.action_down: 
    log.e (TAG, "dispatchtouchevent action_down"); 
    break; 
   Case Motionevent.action_move: 
    log.e (TAG, "dispatchtouchevent action_move"); 
    break; 
   Case MOTIONEVENT.ACTION_UP: 
    log.e (TAG, "dispatchtouchevent action_up"); 
    break;  
   Default: Break 
    ; 
   } 
   Return Super.dispatchtouchevent (event); 
  } 

GetParent (). Requestdisallowintercepttouchevent (True); This way, even if ViewGroup return true at move time, the child view can still capture the go and up event.
Note: If ViewGroup in the onintercepttouchevent (EV) Action_down directly return true, then the child view is no way to capture the event!

Summary
about the code flow above has been summed up ~
1, if ViewGroup found to be able to handle the event view, then directly to the child view processing, their own ontouchevent will not be triggered;
2, you can intercept the Child view's event (that is, return true) through the onintercepttouchevent (EV) method, and give the event to itself, then execute its own corresponding Ontouchevent method
3, The child view can be invoked by calling GetParent (). Requestdisallowintercepttouchevent (True); Prevent ViewGroup from intercepting its move or up event;
Well, what can be done in practical applications?
For example, you embed a edittext in the ScrollView, and when the text content in EditText is too much out of range, you want to slide up and down so that the text in the EditText scrolls out, but you find that the scroll is ScrollView. At this time we set the EditText Ontouch event, in the Ontouch set does not let ScrollView intercept my event, finally when up the state change back.

@Override Public
Boolean Ontouch (View view, Motionevent motionevent) {
  if (view.getid () = = R.id.tousucontentedittext && Canverticalscroll (tousucontentedittext))) {
   view.getparent (). Requestdisallowintercepttouchevent (true);
   if (motionevent.getaction () = = motionevent.action_up) {
    view.getparent (). Requestdisallowintercepttouchevent ( false);
   }
  return false;
 }

Private Boolean Canverticalscroll (EditText edittext) {
  int scrolly = edittext.getscrolly ();
  int scrollrange = Edittext.getlayout (). GetHeight ();
  int scrollextent = Edittext.getheight ()-Edittext.getcompoundpaddingtop ()-Edittext.getcompoundpaddingbottom ();
  int scrolldifference = scrollrange-scrollextent;
  if (scrolldifference = = 0) {return
   false;
  }
  Return (scrolly > 0) | | (Scrolly < scrollDifference-1);
 }

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.