Skip to content

Commit b122563

Browse files
mdvaccafacebook-github-bot
authored andcommitted
Implement SnapToAlignment in ReactHorizontalScrollView
Summary: This diff implements the SnapToAlignment functionality in ReactHorizontalScrollView for RN Android. In order to use SnapToAlignment, the pagingEnabled prop should be set Based on the documentation the behavior implemented in this diff is more "advanced" than the one implemendted in RNiOS, because it let you snap without specifying any interval nor offset (it calculates the intervals in real time based on the size of its content) I still need to verify how different RNiOS and RN Android behaviors are changelog: [Android][Added] Implement SnapToAlignment in ReactHorizontalScrollView Reviewed By: JoshuaGross Differential Revision: D31174544 fbshipit-source-id: 204a82f55e3b7598124ce2528d8ad7d854c0ac77
1 parent deec1db commit b122563

File tree

2 files changed

+74
-1
lines changed

2 files changed

+74
-1
lines changed

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

+35-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77

88
package com.facebook.react.views.scroll;
99

10+
import static com.facebook.react.views.scroll.ReactScrollViewHelper.SNAP_ALIGNMENT_CENTER;
1011
import static com.facebook.react.views.scroll.ReactScrollViewHelper.SNAP_ALIGNMENT_DISABLED;
12+
import static com.facebook.react.views.scroll.ReactScrollViewHelper.SNAP_ALIGNMENT_END;
13+
import static com.facebook.react.views.scroll.ReactScrollViewHelper.SNAP_ALIGNMENT_START;
1114

1215
import android.animation.Animator;
1316
import android.animation.ObjectAnimator;
@@ -23,6 +26,7 @@
2326
import android.view.KeyEvent;
2427
import android.view.MotionEvent;
2528
import android.view.View;
29+
import android.view.ViewGroup;
2630
import android.view.accessibility.AccessibilityEvent;
2731
import android.widget.HorizontalScrollView;
2832
import android.widget.OverScroller;
@@ -912,7 +916,7 @@ private void flingAndSnap(int velocityX) {
912916
}
913917

914918
// pagingEnabled only allows snapping one interval at a time
915-
if (mSnapInterval == 0 && mSnapOffsets == null) {
919+
if (mSnapInterval == 0 && mSnapOffsets == null && mSnapToAlignment == SNAP_ALIGNMENT_DISABLED) {
916920
smoothScrollAndSnap(velocityX);
917921
return;
918922
}
@@ -955,6 +959,36 @@ private void flingAndSnap(int velocityX) {
955959
}
956960
}
957961
}
962+
} else if (mSnapToAlignment != SNAP_ALIGNMENT_DISABLED) {
963+
ViewGroup contentView = (ViewGroup) getContentView();
964+
for (int i = 1; i < contentView.getChildCount(); i++) {
965+
View item = contentView.getChildAt(i);
966+
int itemStartOffset;
967+
switch (mSnapToAlignment) {
968+
case SNAP_ALIGNMENT_CENTER:
969+
itemStartOffset = item.getLeft() - (width - item.getWidth()) / 2;
970+
break;
971+
case SNAP_ALIGNMENT_START:
972+
itemStartOffset = item.getLeft();
973+
break;
974+
case SNAP_ALIGNMENT_END:
975+
itemStartOffset = item.getLeft() - (width - item.getWidth());
976+
break;
977+
default:
978+
throw new IllegalStateException("");
979+
}
980+
if (itemStartOffset <= targetOffset) {
981+
if (targetOffset - itemStartOffset < targetOffset - smallerOffset) {
982+
smallerOffset = itemStartOffset;
983+
}
984+
}
985+
986+
if (itemStartOffset >= targetOffset) {
987+
if (itemStartOffset - targetOffset < largerOffset - targetOffset) {
988+
largerOffset = itemStartOffset;
989+
}
990+
}
991+
}
958992
} else {
959993
double interval = (double) getSnapInterval();
960994
double ratio = (double) targetOffset / interval;

packages/rn-tester/js/examples/ScrollView/ScrollViewSimpleExample.js

+39
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,45 @@ class ScrollViewSimpleExample extends React.Component<{...}> {
6161
])}
6262
</ScrollView>,
6363
);
64+
items.push(
65+
<ScrollView
66+
key={'scrollViewSnapStart'}
67+
horizontal
68+
snapToAlignment={'start'}
69+
pagingEnabled>
70+
{this.makeItems(NUM_ITEMS, [
71+
styles.itemWrapper,
72+
styles.horizontalItemWrapper,
73+
styles.horizontalPagingItemWrapper,
74+
])}
75+
</ScrollView>,
76+
);
77+
items.push(
78+
<ScrollView
79+
key={'scrollViewSnapCenter'}
80+
horizontal
81+
snapToAlignment={'center'}
82+
pagingEnabled>
83+
{this.makeItems(NUM_ITEMS, [
84+
styles.itemWrapper,
85+
styles.horizontalItemWrapper,
86+
styles.horizontalPagingItemWrapper,
87+
])}
88+
</ScrollView>,
89+
);
90+
items.push(
91+
<ScrollView
92+
key={'scrollViewSnapEnd'}
93+
horizontal
94+
snapToAlignment={'end'}
95+
pagingEnabled>
96+
{this.makeItems(NUM_ITEMS, [
97+
styles.itemWrapper,
98+
styles.horizontalItemWrapper,
99+
styles.horizontalPagingItemWrapper,
100+
])}
101+
</ScrollView>,
102+
);
64103

65104
const verticalScrollView = (
66105
<ScrollView style={styles.verticalScrollView}>{items}</ScrollView>

0 commit comments

Comments
 (0)