I open source a convenient RecyclerView top top Android library, welcome you to visit github.com/lizijin/Sti… , if you use this library, please give your valuable comments.

It currently supports the following features:

  1. Support single type top suction function
  2. Support multiple types of top suction function
  3. Enable or disable the top suction function
  4. Support the function of suction top in specified position
  5. Supports setting top offset
  6. Support custom RecyclerView Item top boundary custom
  7. It works seamlessly with AppBarLayout

1. Problem description

Recently, I have been working on a shopping cart + recommended products function. Combining RecyclerView StaggeredGridLayoutManager, complete waterfall streaming style layout. When you’re done, you notice that when you switch TAB and go back to the shopping cart page, the page is slightly offset. The diagram below. Original “qiqiaxiangmelon seed price ¥9.90” close to TAB column. After switching TAB again and coming back, “Qiaqiaiguanzi price ¥9.90” unexpectedly disappeared.

When you find this problem, you first roll back to the previous code using the GridLayoutManager layout. The GridLayoutManager does not have this problem on run. The culprit is StaggeredGridLayoutManager appears problem.

2. Problem analysis

2.1 have taken place in the shopping cart page migration, so must call the StaggeredGridLayoutManager the fill method.

2.2 the fill method will be called to layoutDecoratedWithMargins method, give the View layout on the RV

2.3 layoutDecorateWithMargins otherStart, start, otherEnd, end parameters respectively the layout of the left, top, right, bottom. The offset indicates that the start and end parameters have been changed. Start the assignment in the following StaggeredGridLayoutManager# the fill method

2.4 StaggeredGridLayoutManager# getMaxEnd method

2.5 StaggeredGridLayoutManager# Span# getEndLine method

Determines whether mCachedEnd is set to invalid. If set to invalid then the View’s top position will be recalculated. I think I found the problem. So where is mCachedEnd assigned to INVALID_LINE? Make a discovery

2.6 StaggeredGridLayoutManager# Span# invalidateCache method

2.7 Find out who called invalidateCache

2.8 StaggeredGridLayoutManager# Span# clear method

2.9 Finding out who called the clear method

2.10 StaggeredGridLayoutManager# onDetachedFromWindow method is as follows

2.11 the switch trigger onDetachedFromWindow methods from the View TAB, and emptied all the layout in the StaggeredGridLayoutManager baseline, EndLine. Returning to the shopping cart interface will rearrange the first View visible in the current RecyclerView from 0, resulting in an offset. The GridLayoutManager did not find the offset. Compare their implementation of the onDetachedFromWindow method.

3. Solutions

Solution a: rewrite StaggeredGridLayoutManager onDetachedFromWindow. nothing to do

Solution 2: use StaggeredGridLayoutManager SavedState. As you can see from the code, SavedState holds the parameters for the waterfall flow layout. So we can call onSaveInstanceState before onDetachedFromWindow is called, in onAttachedToWindow

The final effect is as follows