Skip to content

Commit ead7b97

Browse files
ryancatfacebook-github-bot
authored andcommitted
Fix fling and snap in recycler viewgroup where children views not fill 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
1 parent 583471b commit ead7b97

File tree

2 files changed

+28
-2
lines changed

2 files changed

+28
-2
lines changed

ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -968,6 +968,8 @@ private void flingAndSnap(int velocityX) {
968968
maximumOffset);
969969
} else {
970970
ViewGroup contentView = (ViewGroup) getContentView();
971+
int smallerChildOffset = largerOffset;
972+
int largerChildOffset = smallerOffset;
971973
for (int i = 0; i < contentView.getChildCount(); i++) {
972974
View item = contentView.getChildAt(i);
973975
int itemStartOffset =
@@ -983,7 +985,16 @@ private void flingAndSnap(int velocityX) {
983985
largerOffset = itemStartOffset;
984986
}
985987
}
988+
989+
smallerChildOffset = Math.min(smallerChildOffset, itemStartOffset);
990+
largerChildOffset = Math.max(largerChildOffset, itemStartOffset);
986991
}
992+
993+
// For Recycler ViewGroup, the maximumOffset can be much larger than the total heights of
994+
// items in the layout. In this case snapping is not possible beyond the currently rendered
995+
// children.
996+
smallerOffset = Math.max(smallerOffset, smallerChildOffset);
997+
largerOffset = Math.min(largerOffset, largerChildOffset);
987998
}
988999
} else {
9891000
double interval = getSnapInterval();
@@ -994,7 +1005,9 @@ private void flingAndSnap(int velocityX) {
9941005

9951006
// Calculate the nearest offset
9961007
int nearestOffset =
997-
targetOffset - smallerOffset < largerOffset - targetOffset ? smallerOffset : largerOffset;
1008+
Math.abs(targetOffset - smallerOffset) < Math.abs(largerOffset - targetOffset)
1009+
? smallerOffset
1010+
: largerOffset;
9981011

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

ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java

+14-1
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,8 @@ private void flingAndSnap(int velocityY) {
747747
maximumOffset);
748748
} else {
749749
ViewGroup contentView = (ViewGroup) getContentView();
750+
int smallerChildOffset = largerOffset;
751+
int largerChildOffset = smallerOffset;
750752
for (int i = 0; i < contentView.getChildCount(); i++) {
751753
View item = contentView.getChildAt(i);
752754
int itemStartOffset;
@@ -774,7 +776,16 @@ private void flingAndSnap(int velocityY) {
774776
largerOffset = itemStartOffset;
775777
}
776778
}
779+
780+
smallerChildOffset = Math.min(smallerChildOffset, itemStartOffset);
781+
largerChildOffset = Math.max(largerChildOffset, itemStartOffset);
777782
}
783+
784+
// For Recycler ViewGroup, the maximumOffset can be much larger than the total heights of
785+
// items in the layout. In this case snapping is not possible beyond the currently rendered
786+
// children.
787+
smallerOffset = Math.max(smallerOffset, smallerChildOffset);
788+
largerOffset = Math.min(largerOffset, largerChildOffset);
778789
}
779790
} else {
780791
double interval = (double) getSnapInterval();
@@ -785,7 +796,9 @@ private void flingAndSnap(int velocityY) {
785796

786797
// Calculate the nearest offset
787798
int nearestOffset =
788-
targetOffset - smallerOffset < largerOffset - targetOffset ? smallerOffset : largerOffset;
799+
Math.abs(targetOffset - smallerOffset) < Math.abs(largerOffset - targetOffset)
800+
? smallerOffset
801+
: largerOffset;
789802

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

0 commit comments

Comments
 (0)