Skip to content

Instantly share code, notes, and snippets.

@heruoxin
Last active March 29, 2022 14:30
Show Gist options
  • Save heruoxin/8882f7b70618422102105e46d6cb3efd to your computer and use it in GitHub Desktop.
Save heruoxin/8882f7b70618422102105e46d6cb3efd to your computer and use it in GitHub Desktop.
LinearLayoutManager with fixed computeVerticalScrollOffset()
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import java.util.HashMap;
import java.util.Map;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
/**
* @author heruoxin @ CatchingNow Inc.
* @since 2019-08-04
*
* Based on:
* https://medium.com/@rituel521/improving-accuracy-of-computeverticalscrolloffset-for-linearlayoutmanager-38699a9d03b
* Fixed an issue that ignored paddingTop
*/
public class AdvancedLinearLayoutManager extends LinearLayoutManager {
public AdvancedLinearLayoutManager(Context context) {
super(context);
}
public AdvancedLinearLayoutManager(Context context, int orientation, boolean reverseLayout) {
super(context, orientation, reverseLayout);
}
public AdvancedLinearLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
// map of child adapter position to its height.
@SuppressLint("UseSparseArrays")
private Map<Integer, Integer> childSizesMap = new HashMap<>();
@Override
public void onLayoutCompleted(RecyclerView.State state) {
super.onLayoutCompleted(state);
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
if (child != null) childSizesMap.put(getPosition(child), getDecoratedMeasuredHeight(child));
}
}
@Override
public int computeVerticalScrollOffset(RecyclerView.State state) {
if (getChildCount() == 0) return 0;
int firstChildPosition = findFirstVisibleItemPosition();
View firstChild = findViewByPosition(firstChildPosition);
if (firstChild == null) return super.computeVerticalScrollOffset(state);
int scrolledY = - getDecoratedTop(firstChild);
for (int i = 0; i < firstChildPosition; i++) {
Integer size = childSizesMap.get(i);
scrolledY += size == null ? 0 : size;
}
return scrolledY + getPaddingTop();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment