Skip to content

Commit

Permalink
Extend ScrollView.snapToAlignments in RN Android to reach feature par…
Browse files Browse the repository at this point in the history
…ity with RN iOS

Summary:
This diff extends the current implementation of ScrollView.snapToAlignments from RN Android to reach feature parity with RNiOS

changelog: [Android][Changed] Implement ScrollView.snapToAlignments in RN Android

Reviewed By: javache

Differential Revision: D31206398

fbshipit-source-id: b6534965c476a0a4745ac98b419cbe05dc5c746e
  • Loading branch information
mdvacca authored and facebook-github-bot committed Sep 29, 2021
1 parent e774c03 commit 04184ef
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -960,37 +960,45 @@ private void flingAndSnap(int velocityX) {
}
}
} 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.getLeft() - (width - item.getWidth()) / 2;
break;
case SNAP_ALIGNMENT_START:
itemStartOffset = item.getLeft();
break;
case SNAP_ALIGNMENT_END:
itemStartOffset = item.getLeft() - (width - item.getWidth());
break;
default:
throw new IllegalStateException("Invalid SnapToAlignment value: " + mSnapToAlignment);
}
if (itemStartOffset <= targetOffset) {
if (targetOffset - itemStartOffset < targetOffset - smallerOffset) {
smallerOffset = itemStartOffset;
if (mSnapInterval > 0) {
double ratio = (double) targetOffset / mSnapInterval;
smallerOffset =
Math.max(
getItemStartOffset(
mSnapToAlignment,
(int) (Math.floor(ratio) * mSnapInterval),
mSnapInterval,
width),
0);
largerOffset =
Math.min(
getItemStartOffset(
mSnapToAlignment,
(int) (Math.ceil(ratio) * mSnapInterval),
mSnapInterval,
width),
maximumOffset);
} else {
ViewGroup contentView = (ViewGroup) getContentView();
for (int i = 1; i < contentView.getChildCount(); i++) {
View item = contentView.getChildAt(i);
int itemStartOffset =
getItemStartOffset(mSnapToAlignment, item.getLeft(), item.getWidth(), width);
if (itemStartOffset <= targetOffset) {
if (targetOffset - itemStartOffset < targetOffset - smallerOffset) {
smallerOffset = itemStartOffset;
}
}
}

if (itemStartOffset >= targetOffset) {
if (itemStartOffset - targetOffset < largerOffset - targetOffset) {
largerOffset = itemStartOffset;
if (itemStartOffset >= targetOffset) {
if (itemStartOffset - targetOffset < largerOffset - targetOffset) {
largerOffset = itemStartOffset;
}
}
}
}
} else {
double interval = (double) getSnapInterval();
double interval = getSnapInterval();
double ratio = (double) targetOffset / interval;
smallerOffset = (int) (Math.floor(ratio) * interval);
largerOffset = Math.min((int) (Math.ceil(ratio) * interval), maximumOffset);
Expand Down Expand Up @@ -1073,6 +1081,25 @@ private void flingAndSnap(int velocityX) {
}
}

private int getItemStartOffset(
int snapToAlignment, int itemStartPosition, int itemWidth, int viewPortWidth) {
int itemStartOffset;
switch (snapToAlignment) {
case SNAP_ALIGNMENT_CENTER:
itemStartOffset = itemStartPosition - (viewPortWidth - itemWidth) / 2;
break;
case SNAP_ALIGNMENT_START:
itemStartOffset = itemStartPosition;
break;
case SNAP_ALIGNMENT_END:
itemStartOffset = itemStartPosition - (viewPortWidth - itemWidth);
break;
default:
throw new IllegalStateException("Invalid SnapToAlignment value: " + mSnapToAlignment);
}
return itemStartOffset;
}

private void smoothScrollToNextPage(int direction) {
if (DEBUG_MODE) {
FLog.i(TAG, "smoothScrollToNextPage[%d] direction %d", getId(), direction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -743,32 +743,52 @@ 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 (mSnapInterval > 0) {
double ratio = (double) targetOffset / mSnapInterval;
smallerOffset =
Math.max(
getItemStartOffset(
mSnapToAlignment,
(int) (Math.floor(ratio) * mSnapInterval),
mSnapInterval,
height),
0);
largerOffset =
Math.min(
getItemStartOffset(
mSnapToAlignment,
(int) (Math.ceil(ratio) * mSnapInterval),
mSnapInterval,
height),
maximumOffset);
} else {
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;
if (itemStartOffset >= targetOffset) {
if (itemStartOffset - targetOffset < largerOffset - targetOffset) {
largerOffset = itemStartOffset;
}
}
}
}
Expand Down Expand Up @@ -847,6 +867,25 @@ private void flingAndSnap(int velocityY) {
}
}

private int getItemStartOffset(
int snapToAlignment, int itemStartPosition, int itemHeight, int viewPortHeight) {
int itemStartOffset;
switch (snapToAlignment) {
case SNAP_ALIGNMENT_CENTER:
itemStartOffset = itemStartPosition - (viewPortHeight - itemHeight) / 2;
break;
case SNAP_ALIGNMENT_START:
itemStartOffset = itemStartPosition;
break;
case SNAP_ALIGNMENT_END:
itemStartOffset = itemStartPosition - (viewPortHeight - itemHeight);
break;
default:
throw new IllegalStateException("Invalid SnapToAlignment value: " + mSnapToAlignment);
}
return itemStartOffset;
}

private int getSnapInterval() {
if (mSnapInterval != 0) {
return mSnapInterval;
Expand Down

0 comments on commit 04184ef

Please sign in to comment.