I have heard about NestedScrollingView from my colleagues before, but I haven’t had time to know about it. Recently, it was quite empty, so I started to know about it. NestedScrollingView source code:

public class NestedScrollView extends FrameLayout implements NestedScrollingParent, NestedScrollingChild, ScrollingView
Copy the code

You can see that two previously unseen interfaces are implemented: NestedScrollingParent and NestedScrollingChild, also the subject of this article. Android is through these two interfaces, to achieve nested sliding between child View and parent View. This nested sliding mechanism was provided after Lollipop was released on Android. However, it is also supported in Support V7. At the same time RecycleView and Android 5.0 above the system acoustic View most have already supported nested sliding.

The NestedScrolling mechanism allows parent View and child View to cooperate in scrolling mode. To achieve this interaction mechanism, the parent View should implement the NestedScrollingParent interface. The child View needs to implement the NestedScrollingChild interface. In this mechanism, the sub-view is the initiator, and the parent View receives and responds to the callback.

Four main interfaces

When we write on our own, we will encounter the following four classes (interfaces) :

/ / main interface NestedScrollingChild NestedScrollingParent / / help NestedScrollingChildHelper NestedScrollingParentHelperCopy the code

As mentioned earlier, many Views now implement both interfaces:

  • NestedScrollView already implements the NestedScrollingChild and NestedScrollingParent interfaces
  • RecycleView has implemented NestedScrollingChild
  • CoordinatorLayout implements NestedScrollingParent

So what does it take to implement these two interfaces?

To implement the NestedScrollingChild interface, we need to override the following methods:

Public Boolean startNestedScroll(int axes); public void stopNestedScroll(); Public Boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow); public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow); Public Boolean dispatchNestedPreFling(float velocityX, float velocityY); public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed); Public Boolean dispatchNestedPreFling(float velocityX, float velocityY); / / set can slide public void setNestedScrollingEnabled (Boolean enabled). Public Boolean isNestedScrollingEnabled ();Copy the code

To implement the NestedScrollingParent interface, we need to override the following methods:

Public Boolean onStartNestedScroll(View child, View Target, int nestedScrollAxes); public Boolean onStartNestedScroll(View child, View Target, int nestedScrollAxes); public void onNestedScrollAccepted(View child, View target, int nestedScrollAxes); public void onStopNestedScroll(View target); Public void onNestedPreScroll(View target, int dx, int dy, int[] consumed); public void onNestedScroll(View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed); Public Boolean onNestedPreFling(View Target, float velocityX, float velocityY); public Boolean onNestedPreFling(View Target, float velocityX, float velocityY); public boolean onNestedFling(View target, float velocityX, float velocityY, boolean consumed);Copy the code

 

Now we have some idea, but what is the logical relationship between these methods?

Calling process

The whole process is like this

The child view The parent view
startNestedScroll OnStartNestedScroll, onNestedScrollAccepted
dispatchNestedPreScroll onNestedPreScroll
dispatchNestedScroll onNestedScroll
stopNestedScroll onStopNestedScroll

 

 

 

 

 

 

 

 

Specific instructions are as follows:

  • In child view need to slide for example ACTION_DOWN will call startNestedScroll (ViewCompat. SCROLL_AXIS_HORIZONTAL | Viewcompat.scroll_axis_vertical) to tell the parent view that it is about to start sliding (essentially finding a parent that can nest scrolling with the child).
  • The parent view will receive the onStartNestedScroll callback and decide whether or not to respond with the child view. This method returns true if a match is required. And then the onStartNestedScroll () callback will be called.
  • On the sliding event but child view haven’t handle before you can call dispatchNestedPreScroll (0, dy, consumed, offsetInWindow) this method pass events to the parent view that the parent view So you can get the slide information from the child view in the onNestedPreScroll method, and then process it and pass it to the child view through consumed.
  • After dispatchNestedPreScroll (), the child can do its own scrolling.
  • If the parent view needs to handle an event after the child view has been sliding it can call dispatchNestedScroll after the child view has handled the event and then the parent view will get a callback in onNestedScroll.
  • Finally, the slide ends, call onStopNestedScroll() to indicate the end of this process.

Once the process is clear, let’s take a look at some of the specific meanings of the methods to make it easier to understand.

public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) ;
Copy the code

The first two arguments to this method tell the parent View how far to scroll; The third and fourth arguments are used by the child view to obtain the distance consumed by the parent view and the offset of the parent view position. The consumed parameter is an array of int length 2. The first element is the scrolling distance in the x direction consumed by the parent view. The second element is the scrolling distance in the y direction consumed by the parent view. If these two values are not 0, then the child view needs to make some corrections to the scrolling amount. Because we have this parameter, we can handle the scroll events more clearly, not like before a bunch of scroll parameters confused.

This method returns true if the parent consumes some or all of the distance.

public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int[] offsetInWindow);
Copy the code

This method is called after the child view has rolled itself and asks the parent view if it wants the remaining unrolled.

The first four parameters are input parameters, used to tell the parent view the consumed and unconsumed distance, and the last parameter is output parameter, used by the child view to get the offset of the parent view position.

Returned value: true if the event was dispatched, false if it could not be dispatched.

public void stopNestedScroll();
Copy the code

Finally, stopNestedScroll() corresponds to startNestedScroll(int axes) to end the nested scroll process; The two methods related to inertial scrolling are similar to the two methods related to touch scrolling and will not be described here.

 

So here are three examples,

1, github.com/543441727/M…

2. Here’s the code I adapted from the one above to make it work like a drop-down refresh:

Github.com/huanshen/Ne…

3, github.com/qstumn/Refr…

In a nutshell:

Handles the click event in NestedScrollingChild and then initiates a scrolling request;

OnNestedPreScroll handles events in NestedScrollingParent and does not want to consume them;

For a ViewGroup with both interfaces, you need to process it in both. If the subclass is ListView, it can be controlled by the interception of click events, and if it is recyclerView, it can’t be controlled by click events.

 

Reference article:

NestedScrollingParent NestedScrollingChild explanation

Use of NestedScrolling and inertial scrolling

Android — NestedScrolling