Talk about the understanding of Android view event distribution mechanism

Recently, because the project uses a horizontal layout similar to a LinearLayout, there is a textview and button, and then set a click event for the LinearLayout layout. Clicking the textview can trigger the click event. However, it is strange that clicking the button can not trigger it. Then Google came to the solution (rewrite the button, then rewrite the ontouchevent method, and the return value is false), but I don't know the reason. I read the blogs of several great gods these two days, and then I summarized it myself.

MyTextView.Java

Mainactivity is as follows:

Click button and textview to display the following programs:

Click textview:

Why is the result like this? The reference blog has been well written. I'll stand on the shoulders of giants. To sum up, we can see from the above results that when we click View on the screen, the dispatchtouchevent event of view is triggered first. The source code is as follows:

The above montouchlistener is the touch event we set in the activity. When we set it, false is returned in ontouch, so the following ontouchevent method will be executed. It can be seen that the return value of ontouchevent is the return value of dispatchtouchevent. The ontouchevent method has a long source code, so I truncated it.

The fourth line is to judge whether the view can be clicked or long pressed. If so, it returns true. Execute action first in ontouchevent_ Down (finger press). If true is returned, the return value of dispatchtouchevent is true, and the following actions can be executed_ Move and action_ Up method. If false is returned, the following action_ Move and action_ Up will not be implemented. I don't know the specific reason. If I know, I can share it.

Note 1: long press event is the action in ontouchevent_ It is triggered in down (if you set the long press event), and the click onclick event is in action_ Triggered in up.

Now let's analyze the previous example:

Because the button is clickable by default, it will return true in ontouchevent, so the dispatchtouchevent will also return true, followed by action_ Move and action_ Up can then be executed.

Textview is not clickable by default, so false will be returned in ontouchevent, and false will also be returned in dispatchtouchevent, followed by action_ Move and action_ The up cannot be executed, which is consistent with the log printed above.

What happens if we set the ontouch event to return true for textview in the activity? Let's first analyze the source code of dispatchtouchevent:

Since it returns true, we can see from line 10 of the dispatchtouchevent source code that montouchlistener.ontouch (this, event)) returns true, then the if condition is established, dispatchtouchevent directly returns true, and then execute the following action_ Move and action_ Up, (action_move will be executed only if you click and slide). But the subsequent ontouchevent cannot be executed.

The log is as follows:

Action not executed_ Move is because I clicked quickly without sliding. From the log, you can see that the action of dispatchtouchevent has been executed_ After down, the action of dispatchtouchevent is executed_ UP。 However, ontouchevent is not executed.

Now let's start talking about the theme, that is, the problem explained in the preface. Here is my customized ViewGroup:

The XML is as follows:

Mainactivity is as follows:

Note 2: since I am trying to explain the problems in the preface, I will not explain too much about the distribution of touch events in ViewGroup. The process of ViewGroup event distribution is: dispatchtoucheventc > onintercepttouchevent - > then click the event distribution of view with your finger (refer to the event distribution of view mentioned above).

Onintercepttouchevent returns false by default, indicating whether to intercept the event. The source code of dispatchtouchevent of ViewGroup is as follows:

When we click the button, the return value of onintercepttouchevent rewritten in our activity is super.onintercepttouchevent (EV); That is, the default is false, then the if condition of line 25! Onintercepttouchevent (EV)) is true. Enter the if statement, traverse all sub views, and then execute line 51 If (child. Dispatchtouchevent (EV)). As mentioned above, the button is clickable, so the return value of ontouchevent of MyButton is true, that is, the return value of dispatchtouchevent is true. After consuming this event, all click events that will not trigger mlinearlayout. The log is as follows:

So the question is, why set the return value of ontouchevent of MyButton to false, and then click the button to trigger the click event of mlinarlayout?

Let's analyze: if the return value of ontouchevent of MyButton is set to false, then the return value of if (child. Dispatchtouchevent (EV)) in line 51 is false. Why?

The source code of dispatchtouchevent of view was analyzed above. If false is returned, look at the source code of ViewGroup, line 81, final view target = mmotiontarget; Since if (child. Dispatchtouchevent (EV)) in line 51 returns false, no value is assigned to mmotiontarget, and mmotiontarget = = null.

So go to line 85: if (target = = null) / / target = mmotiontarget, so the if condition holds.

Go to line 93: return super. Dispatchtouchevent (EV);

Execute the super. Dispatchtouchevent (EV) in line 9. The super of ViewGroup is view, that is, execute the dispatchtouchevent method of view. Since we set the ontouch event in line 47 of the activity, first execute the ontouch in mlinearlayout.setontouchlistener in the activity, and the ontouch returns false, and then execute the ontouchevent in mylinarlayout.

explain:

Originally, because mylinearlayout is inherited from LinearLayout, it has no clickable or long clickable ability like textview by default. However, in line 38 of the activity, we set the click event, mlinearlayout.setonclicklistener, so mylinarlayout obtains the ability to click.

Therefore, the ontouchevent of mylinarlayout returns true, and then execute the action of the ontouchevent of mylinarlayout_ Up, and the click event is in action_ Executed in up (description 1). All mlinarlayout.setonclicklistener click events are triggered. The log is as follows:

Summary:

1. Touch events are distributed from the top-level view down to the innermost view pressed by your finger. If ontouchevent() of this view returns false, that is, it does not consume touch events, this touch event will go up to the parent layout and call ontouchevent() of its parent layout for processing. If this view returns true, it means that touch events are consumed, then ontouchevent() of the parent layout will not be called.

2. A clickable or longclickable view will always consume touch events, whether it is enabled or disabled.

3. The long press event of view is in action_ To execute the long press event in down, the view must be longclickable. If the set long press event returns true, the clickable event will not be triggered. And cannot generate action_ MOVE。

4. The click event of view is in action_ Execute in up. The precondition for executing click events is the consumption of action_ Down and action_ Move, and when onlongclicklistener is not set, for example, when onlongclicklistener is set, onlongclick() must return false.

5. If the view has ontouchlistener set and the ontouch() method returns true, the ontouchevent() method of the view will not be executed, which also means that the view consumed touch events. If false is returned, the ontouchevent() will continue to be executed.

6. Touch events are distributed from the top view to the innermost view of the finger touch. If the innermost view consumes action_ The action is triggered only when the down event (ontouchlistener is set and ontouch() returns true or the ontouchevent() method returns true) is set_ MOVE,ACTION_ When up occurs, if a ViewGroup intercepts a touch event, the touch event is handed over to the ViewGroup for processing.

The above is the whole content of this article. I hope it will be helpful to your study, and I hope you can support programming tips.

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>