Skip to content

Commit

Permalink
Add a new solution for calculating current card position for carousel…
Browse files Browse the repository at this point in the history
… scrolls

Summary:
### CONTEXT

In an [experiment](https://fb.workplace.com/groups/781375832601068/permalink/1838892143516093/) we recently ran that test different scroll speed for Android Feed carousel ads, we noticed a slow scroll of jump speed  of 1 performs better than faster scrolls.

In the current Android organic implementation, if we set scroll speed to be 1 and snap mode to be center_snap, and scroll softly, we will be taken to the next card in the carousel.

However, if we instead do a strong scroll, we will be taken to the second-next card in the carousel. This is because of the setting for fling and reading of currentPosition in CustomSpeedLinearSnapHelper.

### THIS DIFF
This diff enhances the scrolling behavior of carousel ads by introducing a new support that only snaps to the immediate next card when user scrolls, regardless of the scroll velocity

Reviewed By: pentiumao

Differential Revision: D69197062

fbshipit-source-id: 3d5fc8278761ed9c670f826bdc4b9ec1857e7182
  • Loading branch information
Lihang Liu authored and facebook-github-bot committed Feb 7, 2025
1 parent 4238827 commit da1b6b8
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ public static final class Builder implements RecyclerConfiguration.Builder {
private int mSnapToStartFlingOffset = SnapUtil.SNAP_TO_START_DEFAULT_FLING_OFFSET;
private @SnapMode int mSnapMode = SNAP_NONE;
private int mSnapToStartOffset = 0;
private boolean mIsStrictMode = false;
private @Nullable SnapHelper mSnapHelper;

Builder() {}
Expand Down Expand Up @@ -188,6 +189,11 @@ public Builder snapToStartOffset(int snapToStartOffset) {
return this;
}

public Builder isStrictMode(boolean isStrictMode) {
mIsStrictMode = isStrictMode;
return this;
}

public Builder numColumns(int numColumns) {
mNumColumns = numColumns;
return this;
Expand Down Expand Up @@ -248,7 +254,11 @@ public GridRecyclerConfiguration build() {
(mSnapHelper != null)
? mSnapHelper
: SnapUtil.getSnapHelper(
mSnapMode, mDeltaJumpThreshold, mSnapToStartFlingOffset, mSnapToStartOffset);
mSnapMode,
mDeltaJumpThreshold,
mSnapToStartFlingOffset,
mSnapToStartOffset,
mIsStrictMode);
final GridRecyclerConfiguration configuration =
new GridRecyclerConfiguration(
mOrientation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ public static final class Builder implements RecyclerConfiguration.Builder {

private int mSnapToStartOffset = 0;

private boolean mIsStrictMode = false;

private @Nullable SnapHelper mSnapHelper;

Builder() {}
Expand Down Expand Up @@ -215,6 +217,18 @@ public Builder snapToStartOffset(int snapToStartOffset) {
return this;
}

/**
* Controls carousel H-Scroll behaviors. For a hard user scroll (large scroll velocity): if
* strict mode is on, user will scroll from card indexed N to card indexed N+x, where x is
* deltaJumpThreshold if strict mode is off, user will scroll from card indexed N to card
* indexed N+x+1; For a soft user scroll (small scroll velocity): the scroll behavior is the
* same regardless of strict mode
*/
public Builder isStrictMode(boolean isStrictMode) {
mIsStrictMode = isStrictMode;
return this;
}

public Builder snapHelper(SnapHelper snapHelper) {
mSnapHelper = snapHelper;
return this;
Expand All @@ -238,7 +252,11 @@ public ListRecyclerConfiguration build() {
(mSnapHelper != null)
? mSnapHelper
: SnapUtil.getSnapHelper(
mSnapMode, mDeltaJumpThreshold, mSnapToStartFlingOffset, mSnapToStartOffset);
mSnapMode,
mDeltaJumpThreshold,
mSnapToStartFlingOffset,
mSnapToStartOffset,
mIsStrictMode);
ListRecyclerConfiguration configuration =
new ListRecyclerConfiguration(
mOrientation,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import android.graphics.PointF;
import android.view.View;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.LinearSnapHelper;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;
Expand All @@ -33,9 +34,15 @@
public class CustomSpeedLinearSnapHelper extends LinearSnapHelper {
private static final float INVALID_DISTANCE = 1f;
private final int mDeltaJumpThreshold;
private final boolean mIsStrictMode;

public CustomSpeedLinearSnapHelper(int deltaJumpThreshold) {
this(deltaJumpThreshold, false);
}

public CustomSpeedLinearSnapHelper(int deltaJumpThreshold, boolean isStrictMode) {
mDeltaJumpThreshold = deltaJumpThreshold;
mIsStrictMode = isStrictMode;
}

@Override
Expand All @@ -55,7 +62,17 @@ public int findTargetSnapPosition(
return RecyclerView.NO_POSITION;
}

final int currentPosition = layoutManager.getPosition(currentView);
int currentPosition;
if (mIsStrictMode) {
if (velocityX > 0 || velocityY > 0) {
currentPosition = ((LinearLayoutManager) layoutManager).findFirstVisibleItemPosition();
} else {
currentPosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();
}
} else {
currentPosition = layoutManager.getPosition(currentView);
}

if (currentPosition == RecyclerView.NO_POSITION) {
return RecyclerView.NO_POSITION;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ public static SnapHelper getSnapHelper(
@SnapMode int snapMode,
int deltaJumpThreshold,
int snapToStartFlingOffset,
int snapToStartOffset) {
int snapToStartOffset,
boolean useExactScrollPosition) {
switch (snapMode) {
case SNAP_TO_CENTER:
return new PagerSnapHelper();
Expand All @@ -71,7 +72,7 @@ public static SnapHelper getSnapHelper(
case SNAP_TO_CENTER_CHILD:
return new LinearSnapHelper();
case SNAP_TO_CENTER_CHILD_WITH_CUSTOM_SPEED:
return new CustomSpeedLinearSnapHelper(deltaJumpThreshold);
return new CustomSpeedLinearSnapHelper(deltaJumpThreshold, useExactScrollPosition);
case SNAP_TO_END:
case SNAP_NONE:
default:
Expand Down

0 comments on commit da1b6b8

Please sign in to comment.