diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java index 5d52faf18130de..7f6e173f328c1e 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java @@ -975,7 +975,7 @@ private void flingAndSnap(int velocityX) { itemStartOffset = item.getLeft() - (width - item.getWidth()); break; default: - throw new IllegalStateException(""); + throw new IllegalStateException("Invalid SnapToAlignment value: " + mSnapToAlignment); } if (itemStartOffset <= targetOffset) { if (targetOffset - itemStartOffset < targetOffset - smallerOffset) { diff --git a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java index 38ba923d613262..06d928544b577b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java +++ b/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java @@ -7,7 +7,10 @@ package com.facebook.react.views.scroll; +import static com.facebook.react.views.scroll.ReactScrollViewHelper.SNAP_ALIGNMENT_CENTER; import static com.facebook.react.views.scroll.ReactScrollViewHelper.SNAP_ALIGNMENT_DISABLED; +import static com.facebook.react.views.scroll.ReactScrollViewHelper.SNAP_ALIGNMENT_END; +import static com.facebook.react.views.scroll.ReactScrollViewHelper.SNAP_ALIGNMENT_START; import android.animation.Animator; import android.animation.ObjectAnimator; @@ -641,6 +644,10 @@ private int predictFinalScrollPosition(int velocityY) { return scroller.getFinalY(); } + private View getContentView() { + return getChildAt(0); + } + /** * This will smooth scroll us to the nearest snap offset point It currently just looks at where * the content is and slides to the nearest point. It is intended to be run after we are done @@ -697,7 +704,7 @@ private void flingAndSnap(int velocityY) { } // pagingEnabled only allows snapping one interval at a time - if (mSnapInterval == 0 && mSnapOffsets == null) { + if (mSnapInterval == 0 && mSnapOffsets == null && mSnapToAlignment == SNAP_ALIGNMENT_DISABLED) { smoothScrollAndSnap(velocityY); return; } @@ -734,6 +741,37 @@ private void flingAndSnap(int velocityY) { } } } + + } else if (mSnapToAlignment != SNAP_ALIGNMENT_DISABLED) { + ViewGroup contentView = (ViewGroup) getContentView(); + for (int i = 1; i < contentView.getChildCount(); i++) { + View item = contentView.getChildAt(i); + int itemStartOffset; + switch (mSnapToAlignment) { + case SNAP_ALIGNMENT_CENTER: + itemStartOffset = item.getTop() - (height - item.getHeight()) / 2; + break; + case SNAP_ALIGNMENT_START: + itemStartOffset = item.getTop(); + break; + case SNAP_ALIGNMENT_END: + itemStartOffset = item.getTop() - (height - item.getHeight()); + break; + default: + throw new IllegalStateException("Invalid SnapToAlignment value: " + mSnapToAlignment); + } + if (itemStartOffset <= targetOffset) { + if (targetOffset - itemStartOffset < targetOffset - smallerOffset) { + smallerOffset = itemStartOffset; + } + } + + if (itemStartOffset >= targetOffset) { + if (itemStartOffset - targetOffset < largerOffset - targetOffset) { + largerOffset = itemStartOffset; + } + } + } } else { double interval = (double) getSnapInterval(); double ratio = (double) targetOffset / interval;