Skip to content

Commit

Permalink
Support snapToInterval for horizontal scrollview on Android
Browse files Browse the repository at this point in the history
Summary:
`snapToInterval` is available on iOS but on android yet. This PR is to add support for `snapToInterval` on android.

Example:

![android_snap](https://cloud.githubusercontent.com/assets/1699429/19086983/39d3ee1c-8a25-11e6-9c84-20f25a751f32.gif)

TO: lelandrichardson spikebrehm
Closes #10242

Differential Revision: D4168527

fbshipit-source-id: de3dd9ac5d9e0fddfce5e5bc0aa6a4f33f1e30b3
  • Loading branch information
Jimmy Zhuang authored and facebook-github-bot committed Jan 3, 2018
1 parent a8391bd commit ddd65f1
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 5 deletions.
4 changes: 2 additions & 2 deletions Libraries/Components/ScrollView/ScrollView.js
Original file line number Diff line number Diff line change
Expand Up @@ -344,10 +344,10 @@ 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"`.
* combination with `snapToAlignment` and `decelerationRate="fast"` on ios.
* Overrides less configurable `pagingEnabled` prop.
*
* @platform ios
* Supported for horizontal scrollview on android.
*/
snapToInterval: PropTypes.number,
/**
Expand Down
19 changes: 18 additions & 1 deletion RNTester/js/ScrollViewSimpleExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,20 @@ class ScrollViewSimpleExample extends React.Component<{}> {
{this.makeItems(NUM_ITEMS, [styles.itemWrapper, styles.horizontalItemWrapper])}
</ScrollView>
);
items.push(
<ScrollView
key={'scrollViewSnap'}
horizontal
snapToInterval={210}
pagingEnabled
>
{this.makeItems(NUM_ITEMS, [
styles.itemWrapper,
styles.horizontalItemWrapper,
styles.horizontalPagingItemWrapper,
])}
</ScrollView>
);

var verticalScrollView = (
<ScrollView style={styles.verticalScrollView}>
Expand All @@ -72,7 +86,10 @@ var styles = StyleSheet.create({
},
horizontalItemWrapper: {
padding: 50
}
},
horizontalPagingItemWrapper: {
width: 200,
},
});

module.exports = ScrollViewSimpleExample;
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class ReactHorizontalScrollView extends HorizontalScrollView implements
private @Nullable String mScrollPerfTag;
private @Nullable Drawable mEndBackground;
private int mEndFillColor = Color.TRANSPARENT;
private int mSnapInterval = 0;
private ReactViewBackgroundManager mReactBackgroundManager;

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

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

public void flashScrollIndicators() {
awakenScrollBars();
}
Expand All @@ -114,7 +119,7 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) {
super.onScrollChanged(x, y, oldX, oldY);

mActivelyScrolling = true;

if (mOnScrollDispatchHelper.onScrollChanged(x, y)) {
if (mRemoveClippedSubviews) {
updateClippingRect();
Expand Down Expand Up @@ -212,6 +217,13 @@ public void getClippingRect(Rect outClippingRect) {
outClippingRect.set(Assertions.assertNotNull(mClippingRect));
}

private int getSnapInterval() {
if (mSnapInterval != 0) {
return mSnapInterval;
}
return getWidth();
}

public void setEndFillColor(int color) {
if (color != mEndFillColor) {
mEndFillColor = color;
Expand Down Expand Up @@ -312,7 +324,7 @@ public void run() {
* scrolling.
*/
private void smoothScrollToPage(int velocity) {
int width = getWidth();
int width = getSnapInterval();
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 @@ -10,8 +10,10 @@
package com.facebook.react.views.scroll;

import android.graphics.Color;
import android.util.DisplayMetrics;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.module.annotations.ReactModule;
import com.facebook.react.uimanager.DisplayMetricsHolder;
import com.facebook.react.uimanager.PixelUtil;
import com.facebook.react.uimanager.ReactClippingViewGroupHelper;
import com.facebook.react.uimanager.Spacing;
Expand Down Expand Up @@ -70,6 +72,12 @@ public void setShowsHorizontalScrollIndicator(ReactHorizontalScrollView view, bo
view.setHorizontalScrollBarEnabled(value);
}

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

@ReactProp(name = ReactClippingViewGroupHelper.PROP_REMOVE_CLIPPED_SUBVIEWS)
public void setRemoveClippedSubviews(ReactHorizontalScrollView view, boolean removeClippedSubviews) {
view.setRemoveClippedSubviews(removeClippedSubviews);
Expand Down

0 comments on commit ddd65f1

Please sign in to comment.