What is sliding nesting?
That is, a view with sliding function, and then nested another view with sliding function, such as recyclerView nested recyclerView.
Two. What is CoordinatorLayout?
Coordinate layout is a super Framelayout that can control the coordinated movement of multiple views. Using behavior. The main principle is that the child view to get the sliding event, before sliding, first ask the parent view, ask the parent view to slide first, if the parent view to slide, then slide, and then slide the rest of the distance to tell the child view, and then the child view to slide. So, if the treatment is not good, you can slide up, for example, the parent view slipped a little, and then the child view slipped a little, you will feel kaka, uncomfortable.
How is behavior?
public static abstract class Behavior<V extends View> { public void onNestedScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, @NestedScrollType int type) { if (type == ViewCompat.TYPE_TOUCH) { onNestedScroll(coordinatorLayout, child, target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed); } } @Deprecated public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, int dx, int dy, @NonNull int[] consumed) { // Do nothing } public void onNestedPreScroll(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, int dx, int dy, @NonNull int[] consumed, @NestedScrollType int type) { if (type == ViewCompat.TYPE_TOUCH) { onNestedPreScroll(coordinatorLayout, child, target, dx, dy, consumed); } } public boolean onNestedFling(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, float velocityX, float velocityY, boolean consumed) { return false; } public boolean onNestedPreFling(@NonNull CoordinatorLayout coordinatorLayout, @NonNull V child, @NonNull View target, float velocityX, float velocityY) { return false; }...Copy the code
Is an abstract class that looks a bit like NestedScrollingParent’s method.
For example, how is onDependentViewChanged called
You can see that CoordinatorLayout registers PreDraw listeners, that is, before the view is drawn, it calls back to the CoordinatorLayout’s onChildViewsChanged,
if (b ! Dependson (this, checkChild, child) {null &&b.layoutDependson (this, checkChild, child)) {..... // The dependent view has changed, and the callback to the view that needs to coordinate the movement has been handled = b.ondependentViewChanged (this, checkChild, child); . }Copy the code
Let’s look at another scenario that uses onNestedPreScroll to implement coordinated motion.
Check out his backtrace
It can be seen that the event is passed from recyclerView, so after the move event reaches RecyclerView, recyclerView acts as NestedScrollingChild2, The CoordinatorLayout, as the NestedScrollingParent2, does it need to slide, does it need to deal with move events? After the CoordinatorLayou finishes processing, Recyclerview to run again. It looks like both the child view and the parent view consume the move event, which is kind of interesting.
Recyclerview call dispatchNestedPreScroll after actual using NestedScrollingChildHelper to deal with,
public boolean dispatchNestedPreScroll(int dx, int dy, @Nullable int[] consumed, @Nullable int[] offsetInWindow, @nestedScrollType int type) {if (isNestedScrollingEnabled()) { Often we can close the nested in the application of sliding ViewParentCompat. OnNestedPreScroll (parent, mView, dx,}Copy the code
And then, at the end of the day, you call back to the CoordinatorLayout, and the CoordinatorLayout walks through each child view, and the child view can decide if it needs to be processed or not.
Analyze the drawing process of BottomSheetBehavior
@Override @SuppressWarnings("unchecked") protected void onLayout(boolean changed, int l, int t, int r, int b) { final Behavior behavior = lp.getBehavior(); // Get the behavior of the childView and call the onLayoutChild of the behavior. You walk without behaviors CoordinatorLayout own onLayoutChild if (behaviors = = null | |! behavior.onLayoutChild(this, child, layoutDirection)) { onLayoutChild(child, layoutDirection); }}}Copy the code
So you can see that if you have a view that sets the behavior, you go to the onLayoutChild method of the behavior. So the layout method is taken over by the behavior.
viewDragHelper = ViewDragHelper.create(parent, dragCallback);
Copy the code
And the last thing you do is actually use the viewDragger to do the drag position
@Override public boolean onLayoutChild( @NonNull CoordinatorLayout parent, @NonNull V child, int layoutDirection) { if (state == STATE_EXPANDED) { ViewCompat.offsetTopAndBottom(child, getExpandedOffset()); } else if (state == STATE_HALF_EXPANDED) { ViewCompat.offsetTopAndBottom(child, halfExpandedOffset); } else if (hideable && state == STATE_HIDDEN) { ViewCompat.offsetTopAndBottom(child, parentHeight); } else if (state == STATE_COLLAPSED) { ViewCompat.offsetTopAndBottom(child, collapsedOffset); } else if (state == STATE_DRAGGING || state == STATE_SETTLING) { ViewCompat.offsetTopAndBottom(child, savedTop - child.getTop()); }}Copy the code
5. After bottomsheet nested recyclerView, recyclerView closes the nested sliding, and slips recyclerView, will bottomsheet move?
Move, do not think that close nesting slide, the parent view will stop blocking events, in fact, the parent view will directly start blocking move events when slopMove.
So how do you drag it all the way to Bottomsheet after you intercept it?
In fact, after the interception, the event goes to the CoordinatorLayout, and then it calls the Behavior, and the behavior uses the ViewDragHelper to drag the view that has the behavior configured.
The key is the following function, which checks whether it intercepts, returns true, intercepts because touchingScrollingChild is false, so it returns true. If the RecyclerView is set to NestedScrollingEnabled, touchingScrollingChild is true, and the parent view does not block the move event, and the Move event goes directly to recyclerView.
@Override public boolean tryCaptureView(@NonNull View child, int pointerId) { Log.i("fengfeng", "tryCaptureView start:" + "child=" + child + " pointId=" + pointerId + " state=" + state); if (state == STATE_DRAGGING) { Log.i("fengfeng", "tryCaptureView false 1"); return false; } if (touchingScrollingChild) { Log.i("fengfeng", "tryCaptureView false 2"); return false; } if (state == STATE_EXPANDED && activePointerId == pointerId) { View scroll = nestedScrollingChildRef ! = null ? nestedScrollingChildRef.get() : null; if (scroll ! = null && scroll.canScrollVertically(-1)) { // Let the content scroll up Log.i("fengfeng", "tryCaptureView false 3"); return false; } } Log.i("fengfeng", "tryCaptureView true 4"); return viewRef ! = null && viewRef.get() == child; } @Override public boolean tryCaptureView(@NonNull View child, int pointerId) { Log.i("fengfeng", "tryCaptureView start:" + "child=" + child + " pointId=" + pointerId + " state=" + state); if (state == STATE_DRAGGING) { Log.i("fengfeng", "tryCaptureView false 1"); return false; } if (touchingScrollingChild) { Log.i("fengfeng", "tryCaptureView false 2"); return false; } if (state == STATE_EXPANDED && activePointerId == pointerId) { View scroll = nestedScrollingChildRef ! = null ? nestedScrollingChildRef.get() : null; if (scroll ! = null && scroll.canScrollVertically(-1)) { // Let the content scroll up Log.i("fengfeng", "tryCaptureView false 3"); return false; } } Log.i("fengfeng", "tryCaptureView true 4"); return viewRef ! = null && viewRef.get() == child; }Copy the code
TouchingScrollingChild is assigned to the Down event to indicate that a view can be used for scroll, for example, recyclerView can be used for scroll.
case MotionEvent.ACTION_DOWN: if (state ! = STATE_SETTLING) { View scroll = nestedScrollingChildRef ! = null ? nestedScrollingChildRef.get() : null; if (scroll ! = null && parent.isPointInChildBounds(scroll, initialX, initialY)) { touchingScrollingChild = true; }}Copy the code
The last
Now all say the Internet winter, in fact nothing more than you on the wrong car, will be some of the skills are quickly eliminated, as long as your own technical ability is strong enough, the cost of the company to change big, how may be cut off! I here specifically for Android development engineers organized a set of [Android advanced learning video], [a full set of Android interview secrets], [Android knowledge points PDF] if you need information friends, you can click on meGitHubIt’s free!