preface

It’s the end of the year and I’m going to put my Android knowledge in order.

Android Skill Book Series:

Android Basics

Android Skill Tree – Animation summary

Android Skill Tree – View summary

Android Skill Tree – Activity summary

Android Skill Tree – View event system summary

Android Skill Tree – Summary of Android storage paths and I/O operations

Android Skill Tree – Multi-process related summary

Android skill Tree – Drawable summary

Basic knowledge of data structures

Android Skill Tree – Array, linked list, hash table basic summary

Android Skill Tree — Basic Knowledge of The Tree

Android Skill Tree – Fragment overview

Basic knowledge of algorithms

Android Skill Tree – Sorting algorithm basics summary

This time I’m going to talk about View’s event system. In particular, the distribution of events in different situations, I will teach you in a very simple way.

It’s the same old thing, the brain map, and then I’ll go over it piece by piece.

Brain map links:View event system

View event system

We learn from specific cases

Basic knowledge of View

For example, our current demand is as follows: there is a button on the interface, and our finger will slide after clicking the button. The button can slide with our finger. (Some of the small suspension Windows on the desktop work similarly, get the idea)

Specific implementation can see I have written before the article, very simple: small Demo knowledge – control Button move to learn Android coordinates

Let’s see, since the button can follow our finger, we must be constantly telling the button where you are right now, since it involves some basic things like View position parameters and so on.

View position argument

Here’s a diagram to make the instructions for getting the values of each parameter clearer:

(!!!!!!!!!!! Here I have drawn more getRawX and getRawY methods. View does not have these two methods. Please note!!!!!)

(!!!!!!!!!!! Here I have drawn more getRawX and getRawY methods. View does not have these two methods. Please note!!!!!)

(!!!!!!!!!!! Here I have drawn more getRawX and getRawY methods. View does not have these two methods. Please note!!!!!)

If you look at this picture, it’s immediately clear.

Note:

Let me draw a picture of getLeft(),getTop(),getTop(),getBottom() in a ViewGroup. Some people will give me the following answer:

Wrong answer

GetLeft (),getTop(),getTop(),getBottom() to get the width and height of the View:

width = getRight() - getLeft();
height = getBottom() - getTop();
Copy the code

Knowledge of View operation

MotinoEvent

What is a MotionEvent? It might be a little confusing to ask you separately, but let’s write down what we usually write about setting up touch listening methods:

view.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        return false; }});Copy the code

See, the argument that’s passed in there is a MotionEvent.

As you can see, a MotionEvent is a touch event. When a user touches the screen, a touch event will be generated, and event-related details (location, time, history, gesture, etc.) will be encapsulated as a MotionEvent object.

The specific introduction is really a lot, Baidu search a lot. It’s too much to go into. I don’t have much to say here.

Special tip!! Many people confuse the view.getx /Y() we mentioned above with motionvent.getx /Y(). There is a difference here. Let me draw another picture just to make the difference.

So the difference is:

A View’s getX/Y() is the distance between the top left corner of its View and the top left corner of its parent View. The getX/Y() of a MotionEvent is the distance from the click to the upper-left corner of your View.

Ps: So when the interviewer asks you for getX/Y(), be sure to ask which one you’re asking for. ! Otherwise it’s easy to get the answer wrong.

TouchSlop

TouchSlop is the minimum distance that the system can recognize to be considered sliding. If your finger is less than that when you swipe across the screen, the system thinks you’re not swiping.

VelocityTracker

We may also want to monitor the speed of the slide, for example, we need to slide fast and slow, the final distance of the move is different, etc. At this point, we must know what the speed of the current user is over time N. This is where we need a Velocity Tracker.

GestureDetector

Let’s take a look at the English translation:

That’s right, since you’re on the screen, you might be swiping, you might be clicking, you might be double-clicking. A lot of cases. So this class can help us listen for different operations.

ScaleGestureDetector

Add a Scale before GestureDetector.

That is obviously proportional gesture monitoring, colloquial is the zoom in and out gesture monitoring.

For example, our requirement is that when viewing pictures, we can zoom in and out with two fingers. Then we can use this ScaleGestureDetector to monitor. Very convenient.

Attached is an article I’ve written before:Picture operation series – (1) gesture zoom picture function

View event distribution mechanism

Three stages of event delivery and classes for event handling

In fact, these two are basic knowledge.

Next, I’ll use a real item for a better understanding of event distribution. If it doesn’t make sense, please take one item: ✧(≖ ≖✿)

Here’s an example:

PS: if the example doesn’t fit, you can comment on it. Because if the example doesn’t fit and misleads the reader, that’s my fault.)





Additional points:

  1. Your boss received the notice is to assign this task, it is impossible to say that the first reaction is to think about whether I should stop this task to do it by myself, do not ask his staff to do it (otherwise why also ask you, please you still want to think about whether to do it by yourself every time). So he doesn’t have interception, so he won’t intercept by default, and his first reaction is to give it directly to his staff.

  2. The supervisor has the right to stop the task and not give it to his subordinates, so he can deal with it himself. After all, the supervisor is not only enough to assign tasks, but I also want to be the supervisor. Maybe because all the subordinates have tasks to do, the supervisor will do some development tasks by himself when he is too busy.

  3. The lowest level developer, there’s no blocking because you’re assigned the task. Who can you give again, stop is also you do, do not stop you and no subordinate can give back the pot, or you do.

So let’s see if it looks like our Activity, ViewGroup, and View:

PS: This dispactchEvent will be called when a touch event is received and passed to a layer. (this method is run when the notification task is received)

Boss-activity: it has the ability to receive notifications, so it calls dispatchTouchEvent(), and then because it can notify the supervisor, so yes

The client notifies the boss that you have a project. The boss's dispatchEvent() is called. The boss.dispatchTouchEvent(){// The boss first inform the supervisor to deal with, if the supervisor replies: boss, you don't need to worry about the next matter. We'll take care of it.if(head. DispatchTouchEvent ()) {return true; // Just finish. } // The app can't be developed, only the boss can do the work (communicate with the customer)returnBoss. OnTouchEvent (); }Copy the code

So there are only dispatchEvent() and onTouchEvent() methods.

Director – ViewGroup

The boss informed the supervisor that there was an APP for your department to develop. The supervisor's dispatchTouchEvent() is called to the supervisor.dispatchTouchEvent(){// The supervisor stops the job and prepares to develop the app himselfif(head. InterceptTouchEvent ()) {returnSupervisor. OnTouchEvent (); // The supervisor also has the ability to do things}else{// If the supervisor does not intercept, the supervisor can notify the developer, and // if the developer tells the supervisor to leave it alone. Our app will do wellif(developer.dispatchTouchEvent ()){return true; // It's over. }else{// If the developer also reports to the manager that he can't handle it. // The manager has to do his own work.returnSupervisor. OnTouchEvent (); }}}Copy the code

So there’s dispatchTouchEvent(), interceptTouchEvent(), onTouchEvent().

Developer-view

The director informed the developers that there was an app to be developed. The developer's dispatchTouchEvent() is invoked by the developer.dispatchTouchEvent() {returnDeveloper. OnTouchEvent (); }Copy the code

So there’s dispatchTouchEvent(), onTouchEvent().

Different return values result in different flows

I know you’ve seen something like this:

Return true, false, super, etc. But that’s really hard to remember. A lot of people ask me how I remember it, but I just use pseudo-code to help me remember what pseudo-code is, and that’s the way it’s expressed. That’s what we’re looking at right now.

The actual code for the Activity:

public boolean dispatchTouchEvent(MotionEvent ev){
    if(ev.getAction == MotionEvent.ACTION_DOWN){ onUserInteraction(); } /** Call the window's superDispatchTouchEvent method and then call the dispatchTouchEvent() method of the ViewGroup(DecorView) below. So let's just think of it this way, because we're notifies the dispatchTouchEvent method of the ViewGroup for our Activity. 1. If this getWindow. SuperDispatchTouchEvent () returnstrue, which is executedreturn trueStatements. 2. If this getWindow. SuperDispatchTouchEvent () returnsfalse, which is executedreturnOnTouchEvent (ev); This one, so only as the topifStatement returnsfalseTo call the Activity's own onTouchEvent() method. * /if(getWindow.superDispatchTouchEvent()){
        return true;
    }
    
    return onTouchEvent(ev);
}
Copy the code

So many people will ask you to override the Activity’s dispatchTouchEvent() method, return true/false, and end the event directly. It is not reasonable to return super for normal distribution. It should actually be described like this:

The Activity’s dispatchTouchEvent method is overridden by default:

@override public Boolean dispatchTouchEvent(MotionEvent ev) { The Activity dispatchTouchEvent method we posted above is called to continue the event distribution. * /return super.dispatchTouchEvent(ev);
}
Copy the code

Return true/false to end the event because super.dispatchTouchEvent(ev) was not called; . So it won’t be distributed and the incident will be over.

What if I write it like this:

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    super.dispatchTouchEvent(ev);
    return true/false;
}
Copy the code

Yes, events will be distributed as well. The method of the child View is also called, rather than saying it’s finished.

ViewGroup

Because we have said above getWindow. SuperDispatchTouchEvent () can be directly understood as to invoke the ViewGroup dispatchTouchEvent ();

ViewGroup pseudocode:

Public Boolean dispatchTouchEvent(MotionEvent ev){public Boolean dispatchTouchEvent(MotionEvent ev){public Boolean dispatchTouchEvent(MotionEvent ev){public Boolean dispatchTouchEvent(MotionEvent ev){public Boolean dispatchTouchEvent(MotionEvent ev){ * /if(onInterceptTouchEvent(ev)){
        return onTouchEvent(ev);
    }else{/** if the ViewGroup does not intercept, it will first distribute to the child, and see what their response isfalse, the ViewGroup can only execute its own onTouchEvent(EV); * /if(child.dispatchTouchEvent(ev)){
            return true;
        }else{
            returnonTouchEvent(ev); }}}Copy the code

View pseudocode:

Public Boolean dispatchTouchEvent(MotionEvent ev){** View returns its own onTouchEvent() */return onTouchEvent();
}
Copy the code

Maybe a lot of people still say that I still don’t understand these codes, ah, I even show you up, you will understand.

In this way, different false/true values are returned in different cases, and the order of execution is known.

Additional information:

Supplement 1:

Of course, there are more complicated cases, we know there are ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL, etc., for example, we directly intercept the Down event in the ViewGroup, or after the Down event is passed to the View, When we intercept at MOVE, we will execute a different:

  1. After the DOWN event is passed to the ViewGroup onInterceptTouchEvent(), this method returns true, indicating that the event is intercepted, indicating that the ViewGroup itself needs to handle the event (the event is not passed DOWN). Call its own onTouchEvent() to handle events (DOWN events will no longer be passed up to the Activity’s onTouchEvent())); Other events in the event column (Move, Up) are passed directly to the ViewGroup onTouchEvent().
  2. If a ViewGroup intercepts a halfway event (such as MOVE), the event is converted to a CANCEL event and passed to the child View that handled the event. This event is no longer passed to the ViewGroup onTouchEvent(); Only incoming events are passed to onTouchEvent() in the ViewGroup.

Supplement 2:

public boolean dispatchTouchEvent(MotionEvent ev){
    return onTouchEvent();
}
Copy the code

In addition to onTouchEvent, there are also onTouch events and onClick events. We continue to use pseudocode to illustrate the rule:

public boolean dispatchTouchEvent(MotionEvent ev){
    
    if(TouchListener is set){if(return value of onTouch){return true; }else{
            returnonTouchEvent(); }}return onTouchEvent();
}

public boolean onTouchEvent() {if(ClickListener is set){execute onClick; }... }Copy the code

The View of sliding

Now that we’ve learned the View’s event system, a lot of people say well, I’ve learned what can be done, and the most obvious thing is that we can use it to resolve a lot of sliding conflicts. Because we can selectively intercept according to actual needs, and then do our own event handling.

So let’s look specifically at the sliding knowledge of View:

I’m not going to give you the basics of View sliding. You can search separately.

It’s basically a sliding conflict in the second View. Let’s take the simplest example of sliding left and right on the outside and up and down on the inside.

The outside slides left and right, the inside slides up and down

For example, if we say that the Angle of slide is within N degrees then we’re sliding inside, and if the Angle is outside N degrees then we’re sliding outside.

  1. External interception defaults to parent interception, and then, if appropriate, disallows parent interception.
public boolean onInterceptTouchEvent(MotionEvent event) {
    boolean intercepted=false;
    int x= (int) event.getX();
    int y= (int) event.getY();
    switch (event.getAction()){
        case MotionEvent.ACTION_DOWN:
            intercepted=false; // It must not be intercepted, otherwise all subsequent ACTION_MOME and ACTION_UP events will be intercepted.break;
        case MotionEvent.ACTION_MOVE:
            if(The parent container requires the current click event){intercepted=true;
            }else {
                intercepted=false;
            }
            break;
        case MotionEvent.ACTION_UP:
            intercepted=false;
            break;
        default:
        break;
    }
    mLastXIntercept=x;
    mLastXIntercept=y;
    return intercepted;
}
Copy the code
  1. Beginning of internal intercept method: the default parent element is not allowed to do to intercept, also is the beginning of child elements is invoked requestDisallowInterceptTouchEvent (true); Method to disable the parent element from intercepting, and then allow the parent element to intercept again under appropriate conditions.
@override public Boolean dispatchTouchEvent(MotionEvent ev) {int x = (int) ev.getx (); int y = (int) ev.getY(); switch (ev.getAction()) {case MotionEvent.ACTION_DOWN: {
            getParent().requestDisallowInterceptTouchEvent(true);
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            int deltaX = x - mLastXIntercept;
            int deltaY = y - mLastYIntercept;
            
            if(the parent container need to click on current events) {getParent () requestDisallowInterceptTouchEvent (false);
            }
            break;
        }
        case MotionEvent.ACTION_UP: {
            break;
        }
        default:{
            break;
        }
    }
    mLastXIntercept = x;
    mLastYIntercept = y;
    return super.dispatchTouchEvent(ev);
}
Copy the code

Also, modify the onInterceptTouchEvent() method of the parent container to prevent it from intercepting, because if it intercepts DOWN, the MOVE and UP methods will not have a chance to reach the code above the child element.

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    int action = ev.getAction();
    if (action == MotionEvent.ACTION_DOWN) {
        return false;
    } else {
        return true; }}Copy the code

conclusion

Welcome to check the correction, 😉… Let’s make it a little harder.