Skip to content

Commit

Permalink
Fix fling and snap in recycler viewgroup where children views not fil…
Browse files Browse the repository at this point in the history
…l up all the scrollable space

Summary:
This diff fixes an edge case where fling and snap failed to find the correct target position when children views not fill up all the scrollable space. In this case, the target position would be calculated as the end of the scrollable space, which case the snap logic to go to the end of the scrollable area, instead of stop at the expected snapping position.

Changelog:
[Android][Fixed] - Fix fling and snap with recycler viewgroup where fling to the end of scrollable distance when it goes over current rendered children views.

Reviewed By: mdvacca

Differential Revision: D32565459

fbshipit-source-id: 319ef6e2d4e1c4deb9e45ed02c1bff7d807575c3
  • Loading branch information
ryancat authored and facebook-github-bot committed Dec 6, 2021
1 parent 583471b commit ead7b97
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -968,6 +968,8 @@ private void flingAndSnap(int velocityX) {
maximumOffset);
} else {
ViewGroup contentView = (ViewGroup) getContentView();
int smallerChildOffset = largerOffset;
int largerChildOffset = smallerOffset;
for (int i = 0; i < contentView.getChildCount(); i++) {
View item = contentView.getChildAt(i);
int itemStartOffset =
Expand All @@ -983,7 +985,16 @@ private void flingAndSnap(int velocityX) {
largerOffset = itemStartOffset;
}
}

smallerChildOffset = Math.min(smallerChildOffset, itemStartOffset);
largerChildOffset = Math.max(largerChildOffset, itemStartOffset);
}

// For Recycler ViewGroup, the maximumOffset can be much larger than the total heights of
// items in the layout. In this case snapping is not possible beyond the currently rendered
// children.
smallerOffset = Math.max(smallerOffset, smallerChildOffset);
largerOffset = Math.min(largerOffset, largerChildOffset);
}
} else {
double interval = getSnapInterval();
Expand All @@ -994,7 +1005,9 @@ private void flingAndSnap(int velocityX) {

// Calculate the nearest offset
int nearestOffset =
targetOffset - smallerOffset < largerOffset - targetOffset ? smallerOffset : largerOffset;
Math.abs(targetOffset - smallerOffset) < Math.abs(largerOffset - targetOffset)
? smallerOffset
: largerOffset;

// if scrolling after the last snap offset and snapping to the
// end of the list is disabled, then we allow free scrolling
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,8 @@ private void flingAndSnap(int velocityY) {
maximumOffset);
} else {
ViewGroup contentView = (ViewGroup) getContentView();
int smallerChildOffset = largerOffset;
int largerChildOffset = smallerOffset;
for (int i = 0; i < contentView.getChildCount(); i++) {
View item = contentView.getChildAt(i);
int itemStartOffset;
Expand Down Expand Up @@ -774,7 +776,16 @@ private void flingAndSnap(int velocityY) {
largerOffset = itemStartOffset;
}
}

smallerChildOffset = Math.min(smallerChildOffset, itemStartOffset);
largerChildOffset = Math.max(largerChildOffset, itemStartOffset);
}

// For Recycler ViewGroup, the maximumOffset can be much larger than the total heights of
// items in the layout. In this case snapping is not possible beyond the currently rendered
// children.
smallerOffset = Math.max(smallerOffset, smallerChildOffset);
largerOffset = Math.min(largerOffset, largerChildOffset);
}
} else {
double interval = (double) getSnapInterval();
Expand All @@ -785,7 +796,9 @@ private void flingAndSnap(int velocityY) {

// Calculate the nearest offset
int nearestOffset =
targetOffset - smallerOffset < largerOffset - targetOffset ? smallerOffset : largerOffset;
Math.abs(targetOffset - smallerOffset) < Math.abs(largerOffset - targetOffset)
? smallerOffset
: largerOffset;

// if scrolling after the last snap offset and snapping to the
// end of the list is disabled, then we allow free scrolling
Expand Down

0 comments on commit ead7b97

Please sign in to comment.