Android advanced learning: Android event distribution onInterceptTouchEvent and onTouchEvent

Source: Internet
Author: User

Http://blog.csdn.net/coder80/article/details/8333904

Recently I was working on a project and needed to customize a View, similar to the horizontal scrolling effect in Launcher. It was originally implemented based on the Workspace class. However, when a child View responds to a Scroll event, the Child View does not respond to the touch event. After analyzing the day, add android: clickable = "true" to the sub-View attribute, and the problem is fixed. The onInterceptTouchEvent and onTouchEvent functions of the Android platform are complex. The key point is its return value. I will use some posts on the Internet for reference and use a simple demo for some analysis. OnInterceptTouchEvent () is a method of ViewGroup to intercept related events before the system triggers onTouchEvent () to the ViewGroup and its various childView. 1. the down event is first passed to the onInterceptTouchEvent () method. 2. if the onInterceptTouchEvent () of the ViewGroup returns false after the down event is processed, the subsequent move, up, and other events will be passed to the ViewGroup first, the onTouchEvent () process is passed to the final target view just like the down event. 3. if the onInterceptTouchEvent () of the ViewGroup returns true after it receives the down event processing, the subsequent move, up and other events will not be passed to onInterceptTouchEvent (), the onTouchEvent () is passed to the ViewGroup like the down event. In addition, childView will not receive any events. 4. if the onTouchEvent () of the view that finally needs to process the event returns false, indicating that the event is not consumed, the event will be passed to the onTouchEvent () processing of the previous view. 5. If the onTouchEvent () of the view that finally needs to process the event returns true, subsequent events can be passed to the onTouchEvent () of the view for processing. A simple demo is used to explain the above information one by one. The three custom classes inherit from LinearLayout and ALayout BLayout CLayout (only code of the ALayout class is pasted, and Code of other classes is similar) public class ALayout extends LinearLayout {public ALayout (Context context) {super (context); // TODO Auto-generated constructor stub} public ALayout (Context context, AttributeSet attrs) {super (context, attrs ); // TODO Auto-generated constructor stub}
Public ALayout (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle); // TODO Auto-generated constructor stub}
@ Overridepublic boolean onInterceptTouchEvent (MotionEvent ev) {// TODO Auto-generated method stubfinal int action = ev. getAction (); switch (action & MotionEvent. ACTION_MASK) {case MotionEvent. ACTION_DOWN: Log. e ("ALayout", "onInterceptTouchEvent ACTION_DOWN called, return =" + super. onInterceptTouchEvent (ev); break; case MotionEvent. ACTION_MOVE: break; case MotionEvent. ACTION_UP: break;} return super. onInterceptTouchEvent (ev) ;}@ Overridepublic boolean onTouchEvent (MotionEvent event) {// TODO Auto-generated method stubfinal int action = event. getAction (); switch (action & MotionEvent. ACTION_MASK) {case MotionEvent. ACTION_DOWN: Log. e ("ALayout", "onTouchEvent ACTION_DOWN called, return =" + super. onTouchEvent (event); break; case MotionEvent. ACTION_MOVE: break; case MotionEvent. ACTION_UP: break;} return super. onTouchEvent (event );}}
The layout file main. xml is as follows:

<RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android"
Xmlns: tools = "http://schemas.android.com/tools"
Android: layout_width = "match_parent"
Android: layout_height = "match_parent">
<Com. example. touchtest. ALayout
Android: id = "@ + id/view_a"
Android: layout_width = "fill_parent"
Android: layout_height = "fill_parent"
Android: background = "# ffff0000"
Android: gravity = "center">
<Com. example. touchtest. blyout
Android: id = "@ + id/view_ B"
Android: layout_width = "250dip"
Android: layout_height = "250dip"
Android: background = "# ff00ff00"
Android: gravity = "center">
<Com. example. touchtest. CLayout
Android: id = "@ + id/view_c"
Android: layout_width = "150dip"
Android: layout_height = "150dip"
Android: background = "# ff0000ff"
Android: gravity = "center">
</Com. example. touchtest. CLayout>
</Com. example. touchtest. blyout>
</Com. example. touchtest. ALayout>
</RelativeLayout>
After running the program, the effect is as follows:

The application running effect is shown in the figure on the left. The red background is ALayout, the green is blyout, and the blue is CLayout. When you click the blue (CLayout) area, view the log as follows:

E/ALayout (10407): onInterceptTouchEvent ACTION_DOWN called, return = false

E/BLayout (10407): onInterceptTouchEvent ACTION_DOWN called, return = false

E/CLayout (10407): onInterceptTouchEvent ACTION_DOWN called, return = false

E/CLayout (10407): onTouchEvent ACTION_DOWN called, return = false

E/BLayout (10407): onTouchEvent ACTION_DOWN called, return = false

E/ALayout (10407): onTouchEvent ACTION_DOWN called, return = false

The log shows that the ACTION_DOWN event is first handled by the onInterceptTouchEvent function. Then it is passed to the onTouchEvent function. The default return value of these two functions is false. Because the ACTION_DOWN event is not consumed by the views A, B, and C, the event is gone. Now modify a bit of content and add an android: clickable = "true" to the property of blyout, that is, the layout file is: <RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com/tools" android: layout_width = "match_parent" android: layout_height = "match_parent"> <com. example. touchtest. ALayout android: id = "@ + id/view_a" android: layout_width = "fill_parent" android: layout_height = "fill_parent" android: background = "# ffff0000" android: gravity = "center"> <com. example. touchtest. BLayout android: id = "@ + id/view_ B" android: layout_width = "250dip" android: layout_height = "250dip"
Android: clickable = "true"
Android: background = "# ff00ff00" android: gravity = "center"> <com. example. touchtest. CLayout android: id = "@ + id/view_c" android: layout_width = "150dip" android: layout_height = "150dip" android: background = "# ff0000ff" android: gravity = "center"> </com. example. touchtest. CLayout> </com. example. touchtest. blyout> </com. example. touchtest. after ALayout> </RelativeLayout> is run, click the blue area. The displayed log information is:
E/ALayout (10764): onInterceptTouchEvent ACTION_DOWN called, return = false
E/BLayout (10764): onInterceptTouchEvent ACTION_DOWN called, return = false
E/CLayout (10764): onInterceptTouchEvent ACTION_DOWN called, return = false
E/CLayout (10764): onTouchEvent ACTION_DOWN called, return = false
E/BLayout (10764): onTouchEvent ACTION_DOWN called, return = true
Since only blyout responds to the click event, the onTouchEvent function consumes this event after the DOWN event is captured. The next MOVE and UP events are passed to blyout. It can be concluded that in onTouchEvent, if the returned value is true, the event is consumed. If the returned value is false, the event is not consumed and will be passed on. Next, perform the third test. Add a Button on CLayout. The layout file is as follows: <RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com/tools" android: layout_width = "match_parent" android: layout_height = "match_parent"> <com. example. touchtest. ALayout android: id = "@ + id/view_a" android: layout_width = "fill_parent" android: layout_height = "fill_parent" android: background = "# ffff0000" android: gravity = "center"> <com. example. touchtest. BLayout android: id = "@ + id/view_ B" android: layout_width = "250dip" android: layout_height = "250dip" android: clickable = "true" android: background = "# ff00ff00" android: gravity = "center"> <com. example. touchtest. CLayout android: id = "@ + id/view_c" android: layout_width = "150dip" android: layout_height = "150dip" android: clickable = "false" android: background = "# ff0000ff" android: gravity = "center"> <Button android: id = "@ + id/button1" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "Button"/> </com. example. touchtest. CLayout> </com. example. touchtest. blyout> </com. example. touchtest. add the Button RESPONSE event processing mBtn = (Button) findViewById (R. id. button1); mBtn. setOnClickListener (new OnClickListener () {public void onClick (View v) {// TODO Auto-generated method stubLog. e ("", "mBtn was click... ") ;}}); effect after running


After clicking the Button, the log information is as follows:

E/ALayout (10856): onInterceptTouchEvent ACTION_DOWN called, return = false

E/BLayout (10856): onInterceptTouchEvent ACTION_DOWN called, return = false

E/CLayout (10856): onInterceptTouchEvent ACTION_DOWN called, return = false

E/(10856): mBtn was click...

According to log analysis, the Button is in the top View, and Btn intercepts the click event. It is not transmitted to B, C, and.

The third test illustrates the "rumors" and the 5

4. if the onTouchEvent () of the view that finally needs to process the event returns false, indicating that the event is not consumed, the event will be passed to the onTouchEvent () processing of the previous view. 5. If the onTouchEvent () of the view that finally needs to process the event returns true, subsequent events can be passed to the onTouchEvent () of the view for processing. Then perform the fourth test. The above code is still used, but an attribute must be added to the View of ALayout. Android: clickable = "true ". And the onInterceptTouchEvent function in ALayout returns true. The modified code is as follows: ALayout. java file @ Overridepublic boolean onInterceptTouchEvent (MotionEvent ev) {// TODO Auto-generated method stubfinal int action = ev. getAction (); switch (action & MotionEvent. ACTION_MASK) {case MotionEvent. ACTION_DOWN: Log. e ("ALayout", "onInterceptTouchEvent ACTION_DOWN called, return = true"); break; case MotionEvent. ACTION_MOVE: break; case MotionEvent. ACTION_UP: break;} // return super. onInter CeptTouchEvent (ev); return true;} The layout file is: <RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android" xmlns: tools = "http://schemas.android.com/tools" android: layout_width = "match_parent" android: layout_height = "match_parent"> <com. example. touchtest. ALayout android: id = "@ + id/view_a" android: layout_width = "fill_parent" android: layout_height = "fill_parent" android: background = "# ffff0000" android: Clickable = "true" android: gravity = "center"> <com. example. touchtest. BLayout android: id = "@ + id/view_ B" android: layout_width = "250dip" android: layout_height = "250dip" android: clickable = "true" android: background = "# ff00ff00" android: gravity = "center"> <com. example. touchtest. CLayout android: id = "@ + id/view_c" android: layout_width = "150dip" android: layout_height = "150dip" android: clickable = "true" android: backg Round = "# ff0000ff" android: gravity = "center"> <Button android: id = "@ + id/button1" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "Button"/> </com. example. touchtest. CLayout> </com. example. touchtest. blyout> </com. example. touchtest. after running ALayout> </RelativeLayout>, click the Button. The log information is as follows: 12-19 22:49:34. 722: E/ALayout (11032): onInterceptTouchEvent ACTION_DOWN called, return = True12-19 22:49:34. 722: E/ALayout (11032): onTouchEvent ACTION_DOWN called, return = true by the fourth test confirms the "Rivers and Lakes rumors" 2 and 3. 2. if the onInterceptTouchEvent () of the ViewGroup returns false after the down event is processed, the subsequent move, up, and other events will be passed to the ViewGroup first, the onTouchEvent () process is passed to the final target view just like the down event. 3. if the onInterceptTouchEvent () of the ViewGroup returns true after it receives the down event processing, the subsequent move, up and other events will not be passed to onInterceptTouchEvent (), the onTouchEvent () is passed to the ViewGroup like the down event. In addition, childView will not receive any events
PS: for an in-depth study on the event distribution mechanism, it is best to start with the source code. In the above test example, we only start with the results and do not "know why ".

Related Article

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.