I visited the Forum and accidentally saw a very good post, which is reproduced as follows:
Opening Speech: Recently, the program has made a small effect, and it needs to use touch. As a result, it is completely confused in the cloud. It just takes a good look at the android touch mechanism ..
Each subclass of viewgroup in Android has the following three methods closely related to touchevent processing:
1) Public Boolean dispatchtouchevent (motionevent eV) is used to distribute touchevent
2) Public Boolean onintercepttouchevent (motionevent eV) This method is used to intercept touchevent
3) The Public Boolean ontouchevent (motionevent eV) method is used to process touchevent
Note: not all view subclasses are described in many tutorials. Only controls that can be added to a view must be distributed, for example, textview itself is the smallest view, so it does not need to be distributed to its subview, and it does not have a subview. Therefore, it does not have dispatch or intercept, and only has touchevent.
Note: The White is the outermost layer, which occupies the entire screen;
Red indicates the middle area, which belongs to a layer in white;
Black is the center area, which must be a layer in red.
Note: they are essentially: linearlayout, rather than relativelayout or other layout.
1. The touch event is handled in the central area.
The layout file is as follows:
- <? XML version = "1.0" encoding = "UTF-8"?>
- <Linearlayout xmlns: Android = "http://schemas.android.com/apk/res/android"
- Android: layout_width = "fill_parent"
- Android: layout_height = "fill_parent"
- Android: Orientation = "vertical">
- <Com. Kris. Touch. widget. touchview
- Android: Id = "@ + ID/view_out"
- Android: layout_width = "fill_parent"
- Android: layout_height = "fill_parent"
- Android: Background = "# fff"
- Android: gravity = "center">
- <Com. Kris. Touch. widget. touchview
- Android: Id = "@ + ID/view_mid"
- Android: layout_width = "300px"
- Android: layout_height = "400px"
- Android: Background = "# f00"
- Android: gravity = "center">
- <Com. Kris. Touch. widget. touchview
- Android: Id = "@ + ID/view_center"
- Android: layout_width = "150px"
- Android: layout_height = "150px"
- Android: Background = "#000"
- Android: gravity = "center"
- Android: clickable = "true">
- </COM. Kris. Touch. widget. touchview>
- </COM. Kris. Touch. widget. touchview>
- </COM. Kris. Touch. widget. touchview>
- </Linearlayout>
Copy code
Note: Android: clickable = "true"
Next, let's take a look at the printed log:
Combined with the above logs, we can look at the action_down event processing process:
Note:
When a touch event occurs (action_down), the system calls the dispatchtouchevent method of the activity to distribute the event. Based on the coordinates of the touch event, the event is passed to the dispatchtouchevent processing of the out, And the out event is called onintercepttouchevent to determine whether the event is handled by itself or to continue distributing it to the sub-view. In this case, because the touch event is not processed in the out, the event is passed to the direct subview (middle) of the out event based on the event coordinates ).
The process of event processing in middle and center is the same as that in middle and center. However, because the center component is clickable, it indicates that it can process touch events, the onintercepttouchevent method in the center transmits the event to the center's ontouchevent method for processing. So far, this touch event has been processed and will not be passed on.
2. No designated person will handle touch events
The layout file is as follows:
- <? XML version = "1.0" encoding = "UTF-8"?>
- <Linearlayout xmlns: Android = "http://schemas.android.com/apk/res/android"
- Android: layout_width = "fill_parent"
- Android: layout_height = "fill_parent"
- Android: Orientation = "vertical">
- <Com. Kris. Touch. widget. touchview
- Android: Id = "@ + ID/view_out"
- Android: layout_width = "fill_parent"
- Android: layout_height = "fill_parent"
- Android: Background = "# fff"
- Android: gravity = "center">
- <Com. Kris. Touch. widget. touchview
- Android: Id = "@ + ID/view_mid"
- Android: layout_width = "300px"
- Android: layout_height = "400px"
- Android: Background = "# f00"
- Android: gravity = "center">
- <Com. Kris. Touch. widget. touchview
- Android: Id = "@ + ID/view_center"
- Android: layout_width = "150px"
- Android: layout_height = "150px"
- Android: Background = "#000"
- Android: gravity = "center">
- </COM. Kris. Touch. widget. touchview>
- </COM. Kris. Touch. widget. touchview>
- </COM. Kris. Touch. widget. touchview>
- </Linearlayout>
Copy code
Note: Android: clickable = "true" is only missing from the last layout"
Next, let's take a look at the printed logs.
Combined with the above logs, we can look at the action_down event processing process:
Note:
The event processing process is roughly the same as that of the previous one. The difference is that in this state, all components will not process the event and the event will not be "consumed" by The ontouchevent method of the center. The event will be reversely transmitted back to the activity layer by layer, if the activity does not process the event, the event disappears (no effect ).
For subsequent move and up events, because the first down event has been determined to be handled by the activity, the up event is directly distributed to its ontouchevent method for processing by the dispatchtouchevent method of the activity.
See the final attachment for the code
Summary:
1) In touchevent, if the returned value is true, this event is consumed. If the returned value is false, this event is not consumed and will be passed on. This is the most basic principle. 2) Two Methods of event transmission:
Tunnel mode: pass down from the root element until the sub-element at the inmost layer or stop the transfer due to a certain condition in a certain mona1 element in the middle.
Bubble mode: transfers the child elements from the inmost layer out of sequence until the root element or a mona1 element in the middle stops transmission due to a certain condition. Android's distribution logic for touch events is that the view is distributed from the upper layer to the lower layer (the dispatchtouchevent function) is similar to the tunnel mode, and then the lower layer first processes the event (montouchlistener and then ontouchevent) and return the processing status (Boolean value) up. If true is returned, the upper layer will not process it. Similar to the Bubble Method
The problem arises. If you want to upload all touch events to the upper layer (only false can be returned to the upper layer), then the lower layer view cannot process subsequent events. Sometimes we need to handle touch events both on the lower and upper layers.
For example, viewflipper is used to detect gestures. We put several images inside, a little like the gallery effect, that is, switching between the left and right slides, but sometimes we want to zoom in and out the images! In this way, there will be a touch event in viewflipper, and a touch event in the image (when the screen boundary of the image size can be dragged, rather than switching between the left and right ).
My first thought was to focus on the Event Callback method. After studying for a long time, I did not achieve what I wanted, even after downloading the source code of gallery and gallery3d for a long time, I can't solve it any more. Here, let's just talk about gallery. Although gallery works in this way, however, people do not implement viewflipper and image. People use a view for unified processing like a game. We can simply understand it as a custom control, in this way, we can handle touch events in a way that is complicated in logic. If we want to be lazy, we can't do anything...
Finally, I tried it all the time. I thought of a feasible solution, but I thought it was not very reliable. That is, we intercepted all the touch in viewflipper, then in his ontouchevent, we first call the imageview ontouchevent event. If true is returned to prove that this event is used by imageview, viewflipper will not happen if imageview returns false, call your own touchevent. the pseudocode is as follows:
- // Customize a myviewflipper that inherits from viewflipper and implements the ontouchevent method,
Copy code
I think he is not reliable because: 1. He interrupted the original Android mechanism and did not advocate it very much.
2. Try to know the control in viewflipper, or get it through a certain path.
3. If there are more controls in viewflipper, it hurts.
Well, if you have any comments or suggestions, let's discuss them together.