Get the basics right before getting started:

1, inheritance RecyclerView. LayoutManager

public class LinearLayoutManager extends RecyclerView.LayoutManager implements
        ItemTouchHelper.ViewDropHandler, RecyclerView.SmoothScroller.ScrollVectorProvider {
}
Copy the code

2, implementation generateDefaultLayoutParams

@Override
public RecyclerView.LayoutParams generateDefaultLayoutParams() {
    return new RecyclerView.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
}
Copy the code

3. Rewrite the isAutoMeasureEnabled or onMeasure method

@Override public boolean isAutoMeasureEnabled() { return true; } // The isAutoMeasureEnabled and onMeasure methods are mutually exclusive. Override one of them as required. // Three layOutManagers of RecyclerView all implement isAutoMeasureEnabled @override public void onMeasure(@NonNull RecyclerView.Recycler recycler, @NonNull RecyclerView.State state, int widthSpec, int heightSpec) { super.onMeasure(recycler, state, widthSpec, heightSpec); }Copy the code

4. Overwrite onLayoutChildren and start filling child Views.

@Override
public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {
    super.onLayoutChildren(recycler, state);
}
Copy the code

This example overrides canScrollVerticall or canScrollHorizontally to determine the sliding direction.

@Override
public boolean canScrollVertically() {
    return true;
}
Copy the code

Rewrite scrollVerticallyBy or scrollHorizontallyBy to do boundary processing, item recycling and reuse logic while sliding

@Override public int scrollVerticallyBy(int dy, RecyclerView.Recycler recycler, Int realDy = dy; int realDy = dy; int realDy = dy; . return realDy ; }Copy the code

7, scrollToPosition() and smoothScrollToPosition() method support

Directly see LinearLayoutManager. ScrollToPosition code:

@Override public void scrollToPosition(int position) { mPendingScrollPosition = position; mPendingScrollPositionOffset = INVALID_OFFSET; if (mPendingSavedState ! = null) { mPendingSavedState.invalidateAnchor(); } requestLayout(); }Copy the code

7.1. Set mPendingScrollPosition to the position to scroll to and call requestLayout (), which calls onLayoutChildren. Will call in the onLayoutChildren updateAnchorFromPendingData () according to the position for the view to see if the view is in the midst of the screen, and then according to the position to judge the view from left to right layout, or from right to left layout

private boolean updateAnchorFromPendingData(RecyclerView.State state, AnchorInfo anchorInfo) { ... If (mPendingScrollPositionOffset = = INVALID_OFFSET) {/ / according to the position for need to scroll to view the view child = findViewByPosition(mPendingScrollPosition); // If the view is in the screen (it may not be fully displayed) = null) { ... / / access to view the left edge of the final int startGap = mOrientationHelper. GetDecoratedStart (child) mOrientationHelper.getStartAfterPadding(); / / if less than 0 not fully display The left edge in screen outside the if (startGap < 0) {anchorInfo. MCoordinate = mOrientationHelper. GetStartAfterPadding (); / / layout anchorInfo from left to right. MLayoutFromEnd = false; return true; } / / use the width of the layoutManager minus the right edge of the view final int endGap = mOrientationHelper. GetEndAfterPadding () mOrientationHelper.getDecoratedEnd(child); / / if the result is less than 0 indicates right edge in the screen outside the if (endGap < 0) {anchorInfo. MCoordinate = mOrientationHelper. GetEndAfterPadding (); / / layout anchorInfo from right to left. MLayoutFromEnd = true; return true; }... If (getChildCount() > 0) {if (getChildCount() > 0) {// Get position of any child, Int pos = getPosition(getChildAt(0)); / / by comparing the current need to scroll to view the position and the current display of the view of the position to determine how to layout anchorInfo. MLayoutFromEnd = mPendingScrollPosition < pos = = mShouldReverseLayout; }... } return true;Copy the code

8, smoothScrollToPosition()

//LinearLayuotManager
    @Override
public void smoothScrollToPosition(RecyclerView recyclerView, RecyclerView.State state,
        int position) {
    LinearSmoothScroller linearSmoothScroller =
            new LinearSmoothScroller(recyclerView.getContext());
    linearSmoothScroller.setTargetPosition(position);
    startSmoothScroll(linearSmoothScroller);
}
Copy the code

8.1 Customized layoutManager implements the ScrollVectorProvider interface

public class LinearLayoutManager extends RecyclerView.LayoutManager implements
        ItemTouchHelper.ViewDropHandler, RecyclerView.SmoothScroller.ScrollVectorProvider {
}
Copy the code

8.2 rewrite computeScrollVectorForPosition method

@Override public PointF computeScrollVectorForPosition(int targetPosition) { if (getChildCount() == 0) { return null; } final int firstChildPos = getPosition(getChildAt(0)); final int direction = targetPosition < firstChildPos ! = mShouldReverseLayout ? 1:1; if (mOrientation == HORIZONTAL) { return new PointF(direction, 0); } else { return new PointF(0, direction); }}Copy the code

9. Recycle View: If you can accurately recycle and reuse Holder during the first layout and sliding, you can directly get Holder in mAttachedScrap and put it directly into mRecyclerPool for recycling. Every time (such as sliding detachAndScrapAttachedViews have call, then go in the cache to useful itemview)

List scrapList = recycler.getscraplist (); RemoveAndRecycleView for (int I = 0; i < scrapList.size(); i++) { RecyclerView.ViewHolder holder = scrapList.get(i); removeView(holder.itemView); recycler.recycleView(holder.itemView); }Copy the code

Otherwise, you need to calculate the start and end index to recycle

private void recycleChildren(RecyclerView.Recycler recycler, int startIndex, int endIndex) { if (startIndex == endIndex) { return; } if (endIndex > startIndex) { for (int i = endIndex - 1; i >= startIndex; i--) { removeAndRecycleViewAt(i, recycler); } } else { for (int i = startIndex; i > endIndex; i--) { removeAndRecycleViewAt(i, recycler); }}}Copy the code

The above steps are required to customize Layoutmananger. Note that the above is not a complete code. In fact, the business logic is still supplemented in each step