Skip to content
6 changes: 2 additions & 4 deletions Libraries/Components/ScrollView/ScrollView.js
Original file line number Diff line number Diff line change
Expand Up @@ -326,11 +326,9 @@ const ScrollView = createReactClass({
/**
* When set, causes the scroll view to stop at multiples of the value of
* `snapToInterval`. This can be used for paginating through children
* that have lengths smaller than the scroll view. Typically used in
* combination with `snapToAlignment` and `decelerationRate="fast"`.
* that have lengths smaller than the scroll view. When used on iOS it is typically combined
* with `snapToAlignment` and `decelerationRate="fast"`.
* Overrides less configurable `pagingEnabled` prop.
*
* @platform ios
*/
snapToInterval: PropTypes.number,
/**
Expand Down
54 changes: 34 additions & 20 deletions RNTester/js/ScrollViewSimpleExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,46 +17,60 @@ var {
ScrollView,
StyleSheet,
Text,
TouchableOpacity
View
} = ReactNative;

var NUM_ITEMS = 20;

class ScrollViewSimpleExample extends React.Component {
static title = '<ScrollView>';
static description = 'Component that enables scrolling through child components.';

makeItems = (nItems: number, styles): Array<any> => {
makeItems = (nItems: number, extraStyle): Array<any> => {
var items = [];
for (var i = 0; i < nItems; i++) {
items[i] = (
<TouchableOpacity key={i} style={styles}>
<View key={i} style={[styles.itemWrapper, extraStyle]}>
<Text>{'Item ' + i}</Text>
</TouchableOpacity>
</View>
);
}
return items;
};

render() {
// One of the items is a horizontal scroll view
var items = this.makeItems(NUM_ITEMS, styles.itemWrapper);
items[4] = (
<ScrollView key={'scrollView'} horizontal={true}>
{this.makeItems(NUM_ITEMS, [styles.itemWrapper, styles.horizontalItemWrapper])}
</ScrollView>
);
getListItem = (item: any, index: number) => {
if (index === 4) {
return (
<ScrollView key="scrollView" horizontal>
{this.makeItems(10, styles.horizontalItemWrapper)}
</ScrollView>
);
}
else if (index === 5) {
return (
<ScrollView
key="scrollViewSnap"
horizontal
snapToInterval={horizontalItemWidth + 2 * itemMargin}
>
{this.makeItems(10, styles.horizontalItemWrapper)}
</ScrollView>
);
}

var verticalScrollView = (
return item;
}

render() {
return (
<ScrollView style={styles.verticalScrollView}>
{items}
{this.makeItems(20).map(this.getListItem)}
</ScrollView>
);

return verticalScrollView;
}
}

const horizontalItemWidth = 140;
const itemMargin = 5;

var styles = StyleSheet.create({
verticalScrollView: {
margin: 10,
Expand All @@ -68,10 +82,10 @@ var styles = StyleSheet.create({
borderWidth: 5,
borderColor: '#a52a2a',
padding: 30,
margin: 5,
margin: itemMargin,
},
horizontalItemWrapper: {
padding: 50
width: horizontalItemWidth,
}
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements
private @Nullable Drawable mEndBackground;
private int mEndFillColor = Color.TRANSPARENT;
private @Nullable ReactViewBackgroundDrawable mReactBackgroundDrawable;
private int mSnapInterval = 0;

public ReactHorizontalScrollView(Context context) {
this(context, null);
Expand Down Expand Up @@ -92,6 +93,10 @@ public void setPagingEnabled(boolean pagingEnabled) {
mPagingEnabled = pagingEnabled;
}

public void setSnapInterval(int snapInterval) {
mSnapInterval = snapInterval;
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
MeasureSpecAssertions.assertExplicitMeasureSpec(widthMeasureSpec, heightMeasureSpec);
Expand Down Expand Up @@ -310,7 +315,7 @@ public void run() {
* scrolling.
*/
private void smoothScrollToPage(int velocity) {
int width = getWidth();
int width = mSnapInterval != 0 ? mSnapInterval : getWidth();
int currentX = getScrollX();
// TODO (t11123799) - Should we do anything beyond linear accounting of the velocity
int predictedX = currentX + velocity;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@

import android.graphics.Color;
import android.view.View;
import android.util.DisplayMetrics;

import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.Spacing;
Expand Down Expand Up @@ -68,6 +70,14 @@ public void setScrollEnabled(ReactHorizontalScrollView view, boolean value) {
view.setScrollEnabled(value);
}

@ReactProp(name = "snapToInterval")
public void setSnapToInterval(ReactHorizontalScrollView view, int snapToInterval) {
view.setPagingEnabled(snapToInterval > 0);
DisplayMetrics screenDisplayMetrics = DisplayMetricsHolder.getScreenDisplayMetrics();
view.setSnapInterval((int)(snapToInterval * screenDisplayMetrics.density));
}


@ReactProp(name = "showsHorizontalScrollIndicator")
public void setShowsHorizontalScrollIndicator(ReactHorizontalScrollView view, boolean value) {
view.setHorizontalScrollBarEnabled(value);
Expand Down