Skip to content

Commit ed75963

Browse files
Abbondanzometa-codesync[bot]
authored andcommitted
Run flingAndSnap logic from ACTION_SCROLL events (#54226)
Summary: Pull Request resolved: #54226 #54226 Joysticks, mouse wheels, and trackpads can issue an `ACTION_SCROLL` event when performing scroll. However, the `ACTION_SCROLL` generic motion event does not run the post touch runnable and paging/snap alignment is not honored when these events are received. To fix this, both ScrollView implementations should call `handlePostTouchScrolling` with a 0 velocity, ensuring that momentum events are sent, fabric scroll state is updated, and `flingAndSnap` is properly called to align to a page. This change adds some checks to queue a runnable that calls `handlePostTouchScrolling` after no more `ACTION_SCROLL` events are received in the same 20ms delay it uses to determine a stable frame. The end result is that snap alignments are correctly honored Changelog: [Android][Fixed] - Controller-driven scroll events now honor paging/snap alignment Reviewed By: javache Differential Revision: D85172309 fbshipit-source-id: 5818777b3c371b3da4aa925a8c840e0da89bf6a4
1 parent 6f84323 commit ed75963

File tree

2 files changed

+64
-0
lines changed

2 files changed

+64
-0
lines changed

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactHorizontalScrollView.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,38 @@ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
804804
return false;
805805
}
806806

807+
// Handle ACTION_SCROLL events (mouse wheel, trackpad, joystick)
808+
if (ev.getActionMasked() == MotionEvent.ACTION_SCROLL) {
809+
float hScroll = ev.getAxisValue(MotionEvent.AXIS_HSCROLL);
810+
if (hScroll != 0) {
811+
// Perform the scroll
812+
boolean result = super.dispatchGenericMotionEvent(ev);
813+
// Schedule snap alignment to run after scrolling stops
814+
if (result
815+
&& (mPagingEnabled
816+
|| mSnapInterval != 0
817+
|| mSnapOffsets != null
818+
|| mSnapToAlignment != SNAP_ALIGNMENT_DISABLED)) {
819+
// Cancel any pending runnable and reschedule
820+
if (mPostTouchRunnable != null) {
821+
removeCallbacks(mPostTouchRunnable);
822+
}
823+
mPostTouchRunnable =
824+
new Runnable() {
825+
@Override
826+
public void run() {
827+
mPostTouchRunnable = null;
828+
// Trigger snap alignment now that scrolling has stopped
829+
handlePostTouchScrolling(0, 0);
830+
}
831+
};
832+
ViewCompat.postOnAnimationDelayed(
833+
this, mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY);
834+
}
835+
return result;
836+
}
837+
}
838+
807839
return super.dispatchGenericMotionEvent(ev);
808840
}
809841

packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/scroll/ReactScrollView.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,38 @@ public boolean dispatchGenericMotionEvent(MotionEvent ev) {
658658
return false;
659659
}
660660

661+
// Handle ACTION_SCROLL events (mouse wheel, trackpad, joystick)
662+
if (ev.getActionMasked() == MotionEvent.ACTION_SCROLL) {
663+
float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
664+
if (vScroll != 0) {
665+
// Perform the scroll
666+
boolean result = super.dispatchGenericMotionEvent(ev);
667+
// Schedule snap alignment to run after scrolling stops
668+
if (result
669+
&& (mPagingEnabled
670+
|| mSnapInterval != 0
671+
|| mSnapOffsets != null
672+
|| mSnapToAlignment != SNAP_ALIGNMENT_DISABLED)) {
673+
// Cancel any pending post-touch runnable and reschedule
674+
if (mPostTouchRunnable != null) {
675+
removeCallbacks(mPostTouchRunnable);
676+
}
677+
mPostTouchRunnable =
678+
new Runnable() {
679+
@Override
680+
public void run() {
681+
mPostTouchRunnable = null;
682+
// Trigger snap alignment now that scrolling has stopped
683+
handlePostTouchScrolling(0, 0);
684+
}
685+
};
686+
ViewCompat.postOnAnimationDelayed(
687+
this, mPostTouchRunnable, ReactScrollViewHelper.MOMENTUM_DELAY);
688+
}
689+
return result;
690+
}
691+
}
692+
661693
return super.dispatchGenericMotionEvent(ev);
662694
}
663695

0 commit comments

Comments
 (0)