Android custom View series

  • Android custom View Paint draws text and lines
  • Android custom View Precautions
  • Canvas for Android custom View
  • Android custom View image shape effects – easy to achieve rounded corners and round images
  • Android custom View dual buffering mechanism and SurfaceView
  • Android custom View invalidate method and postInvalidate method
  • Android custom View Window, View View PL and View of the three processes
  • Android custom View image color processing
  • Android custom View requestLayout method and invalidate method

Sequence of events

(1) A series of events will be generated after finger touches the screen, which can be divided into three types: ACTION_DOWN(finger just touches the screen), ACTION_MOVE(finger moves on the screen) and ACTION_UP(finger loosens from the screen).

(2) An event sequence is ACTION_DOWN–>ACTION_MOVE–>… –>ACTION_UP

The order in which events are delivered

Activity–>Window–> Decor view–> our layout, ViewGroup–> the clickable sub-views in our layout

If our child View does not handle the event, the event will be passed back up:

The clickable sub-view in our layout –> upper ViewGroup–> Decor View–> Window–>Activity

If no event is consumed by any View, the event is eventually passed back to the Activity for processing (the Activity’s onTouchEvent() method is called).

The three methods

ViewGroup has three methods related to event distribution: dispatchTouchEvent, onInterceptTouchEvent and onTouchEvent.

(1) dispatchTouchEvent method

The dispatchTouchEvent method is used for event distribution. This method is called when the event is passed to the current View. The dispatchTouchEvent method contains the specific event distribution logic. The return result is affected by the onTouchEvent method of the current View and the dispatchTouchEvent method of the subordinate View.

(2) onInterceptTouchEvent

The onInterceptTouchEvent method is called inside the dispatchTouchEvent method to determine whether to intercept an event. If the current View intercepts an event, this method is not called again in the same sequence of events and returns a result indicating whether the current event was intercepted. This method is only available in VewGroup, not View.

(3) onTouchEvent method

Called in the dispatchTouchEvent method to handle the click event and returns a result indicating whether the current event is consumed. If not, the current View cannot receive the event again in the same sequence of events.

Priority of onTouchListener, onTouchEvent, and onClickListener

(1) onTouchListener and onTouchEvent are both called in the dispatchTouchEvent method and onClickListener is called in the onTouchEvent method

(2) onTouchListener has a higher priority than onTouchEvent. If onTouchListener returns true, onTouchEvent will not be called, and of course onClickListener will not be called

(3) In onTouchEvent, if the current View has onClickListener set, the onClick method of onClickListener will be called

(4) As long as either the View’s CLICKABLE or LONKG_CLICKABLE is true, the View will consume the current event, that is, the onTouchEvent method will return true.

(5) The LONG_CLICKABLE attribute of a View is false by default, and the CLICKABLE attribute depends on the specific View. The CLICKABLE attribute of a CLICKABLE View is true, and the CLICKABLE attribute of an unclickable View is false.

Event distribution logic in ViewGroup

The event distribution logic in a ViewGroup can be expressed in a piece of pseudo-code

public boolean dispatchTouchEvent(MotionEvent ev) {
    boolean consume = false;
    if (onInterceptTouchEvent(ev)) {
        consume = onTouchEvent();
    }else {
        consume = child.dispatchTouchEvent(ev);
    }
    
    return consume;
}
Copy the code

From the above pseudocode, we can summarize the event distribution process in ViewGroup:

(1) The dispatchTouchEvent method is called when the event is passed to the ViewGroup. If the onInterceptTouchEvent method of the ViewGroup returns true, it intercepts the event, which is passed to the onTouchEvent method of the current ViewGroup.

(2) If the current ViewGroup onInterceptTouchEvent returns false, then the child element’s dispatchTouchEvent method is called, passing the event to the child element.

(3) If the child element does not consume the event, i.e. its dispatchTouchEvent method returns false, the event will be handled by the current ViewGroup itself, and the current ViewGroup’s onTouchEvent will be called. If the current ViewGroup’s dispatchTouchEvent method also returns false, the Activity’s onTouchEvent method will be called if the event is never consumed

(4) It is important to understand that the ViewGroup inherits from the View, and there is no onTouchEvent method in the ViewGroup. The ViewGroup calls its parent class, the View’s dispatchTouchEvent method, to handle the event itself. If it doesn’t consume the event itself, The dispatchTouchEvent method returns false, thus turning the event upstream.

(5) If the ACTION_DOWN event child is not processed (onTouchEvent returns false), the rest of the sequence of events (MOVE and UP events) will not be assigned to the child.

(6) ViewGroup does not intercept any events by default

(7) For ACTION_DOWN events, the ViewGroup will call onInterceptTouchEvent method every time to determine whether the event needs to be intercepted. Once the event needs to be intercepted, the ViewGroup will handle the subsequent ACTION_MOVE and ACTION_UP events. It is not passed to the child View, and the onInterceptTouchEvent method is no longer called. So the onInterceptTouchEvent method is not called for every event.

(8) the child View can be requestDisallowInterceptTouchEvent approach to intervention in the parent element besides ACTION_DOWN unexpected event distribution process

Event distribution logic in View

RequestDisallowInterceptTouchEvent method

RequestDisallowInterceptTouchEvent method used to influence events to intercept strategy of the parent element, requestDisallowInterceptTouchEvent (true), said do not allow the parent to intercept events, this event will be passed to the View. Generally this method subview is used more, can be used to handle sliding conflicts.

Event distribution logic

(1) There is no onInterceptTouchEvent method in the View, so once an event is passed to the View, the View’s dispatchTouchEvent method will be called.

(2) The logical order of events handled by the dispatchTouchEvent method is onTouchListener–>onTouchEvent–>onClickListener.

If onTouchListener is set, the onTouch method will be called. If onTouchListener returns true, the event will be consumed and the event will not be called.

(4) If onTouch returns false, onTouchEvent will be called. If the View has onClickListener set, the onClick method of onClickListener in onTouchEvent will also be called when the ACTION_UP event arrives.

(5) A View consumes events. If the View does not consume ACTION_DOWN events, then ACTION_MOVE and ACTION_UP will not be passed to the View.

Common sliding conflict handling logic

(1) Use the onInterceptTouchEvent method of the parent layout

The idea is to intercept events when the parent layout needs to handle them, and not at all other times. A few caveats:

  • For ACTION_DOWN events, the onInterceptTouchEvent method must return false, because once it returns true, the child element will never receive the event, and that resolves a bug conflict.
  • The main logic is in the ACTION_MOVE processing, the need to block the logic is based on the need to implement
  • Return false for ACTION_UP events, because once the parent returns true, the child View will not accept the ACTION_UP event and will not trigger the onClick event.

(2) on the child View requestDisallowInterceptTouchEvent method

The idea is that the parent intercepts all events except ACTION_DOWN by default, and the child View interferes with the parent’s intercepting strategy as needed in the dispatchTouchEvent method. By default, do not allow the parent to intercept events layout in need parent layout processing events, through requestDisallowInterceptTouchEvent (false) ways to make parent layout processing events, other times are handled by child View.

Note:

  • Similarly, onInterceptTouchEvent must return false for ACTION_DOWN events, and true for other events by default
  • In child View dispatchTouchEvent method for ACTION_DOWN events by calling requestDisallowInterceptTouchEvent (true) do not allow the parent to intercept events layout by default, so that subsequent events are to child View
  • In the child View’s dispatchTouchEvent method, ACTION_MOVE events are handled by the child View by default, and when parent layout processing is required, Call requestDisallowInterceptTouchEvent (false) method to let the parent layout intercept events, to the parent layout.

Welcome to follow my wechat public number, and make progress with me every day!Copy the code