Skip to content

Commit 80b6863

Browse files
Copilotanupriya13
andcommitted
Implement onMomentumScrollEnd and onMomentumScrollBegin for Fabric ScrollView
Co-authored-by: anupriya13 <[email protected]>
1 parent ed4f3a8 commit 80b6863

File tree

4 files changed

+74
-1
lines changed

4 files changed

+74
-1
lines changed

vnext/Microsoft.ReactNative/CompositionSwitcher.idl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ namespace Microsoft.ReactNative.Composition.Experimental
118118
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollPositionChanged;
119119
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollBeginDrag;
120120
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollEndDrag;
121+
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollMomentumBegin;
122+
event Windows.Foundation.EventHandler<IScrollPositionChangedArgs> ScrollMomentumEnd;
121123
void ContentSize(Windows.Foundation.Numerics.Vector2 size);
122124
Windows.Foundation.Numerics.Vector3 ScrollPosition { get; };
123125
void ScrollBy(Windows.Foundation.Numerics.Vector3 offset, Boolean animate);

vnext/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,10 @@ struct CompScrollerVisual : winrt::implements<
711711
void IdleStateEntered(
712712
typename TTypeRedirects::InteractionTracker sender,
713713
typename TTypeRedirects::InteractionTrackerIdleStateEnteredArgs args) noexcept {
714+
if (m_outer->m_inertia) {
715+
// We were in inertia and now we're idle, so momentum scrolling has ended
716+
m_outer->FireScrollMomentumEnd({sender.Position().x, sender.Position().y});
717+
}
714718
m_outer->m_custom = false;
715719
m_outer->m_inertia = false;
716720
}
@@ -725,6 +729,8 @@ struct CompScrollerVisual : winrt::implements<
725729
// 2. tracker has just started gliding into Inertia state
726730
// Fire ScrollEndDrag
727731
m_outer->FireScrollEndDrag({args.NaturalRestingPosition().x, args.NaturalRestingPosition().y});
732+
// Fire momentum scroll begin when we enter inertia
733+
m_outer->FireScrollMomentumBegin({args.NaturalRestingPosition().x, args.NaturalRestingPosition().y});
728734
}
729735
void InteractingStateEntered(
730736
typename TTypeRedirects::InteractionTracker sender,
@@ -985,6 +991,20 @@ struct CompScrollerVisual : winrt::implements<
985991
return m_scrollEndDragEvent.add(handler);
986992
}
987993

994+
winrt::event_token ScrollMomentumBegin(
995+
winrt::Windows::Foundation::EventHandler<
996+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs> const
997+
&handler) noexcept {
998+
return m_scrollMomentumBeginEvent.add(handler);
999+
}
1000+
1001+
winrt::event_token ScrollMomentumEnd(
1002+
winrt::Windows::Foundation::EventHandler<
1003+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs> const
1004+
&handler) noexcept {
1005+
return m_scrollMomentumEndEvent.add(handler);
1006+
}
1007+
9881008
void ScrollPositionChanged(winrt::event_token const &token) noexcept {
9891009
m_scrollPositionChangedEvent.remove(token);
9901010
}
@@ -997,6 +1017,14 @@ struct CompScrollerVisual : winrt::implements<
9971017
m_scrollEndDragEvent.remove(token);
9981018
}
9991019

1020+
void ScrollMomentumBegin(winrt::event_token const &token) noexcept {
1021+
m_scrollMomentumBeginEvent.remove(token);
1022+
}
1023+
1024+
void ScrollMomentumEnd(winrt::event_token const &token) noexcept {
1025+
m_scrollMomentumEndEvent.remove(token);
1026+
}
1027+
10001028
void ContentSize(winrt::Windows::Foundation::Numerics::float2 const &size) noexcept {
10011029
m_contentSize = size;
10021030
m_contentVisual.Size(size);
@@ -1075,6 +1103,14 @@ struct CompScrollerVisual : winrt::implements<
10751103
m_scrollEndDragEvent(*this, winrt::make<CompScrollPositionChangedArgs>(position));
10761104
}
10771105

1106+
void FireScrollMomentumBegin(winrt::Windows::Foundation::Numerics::float2 position) noexcept {
1107+
m_scrollMomentumBeginEvent(*this, winrt::make<CompScrollPositionChangedArgs>(position));
1108+
}
1109+
1110+
void FireScrollMomentumEnd(winrt::Windows::Foundation::Numerics::float2 position) noexcept {
1111+
m_scrollMomentumEndEvent(*this, winrt::make<CompScrollPositionChangedArgs>(position));
1112+
}
1113+
10781114
void UpdateMaxPosition() noexcept {
10791115
m_interactionTracker.MaxPosition(
10801116
{std::max<float>(m_contentSize.x - m_visualSize.x, 0),
@@ -1263,6 +1299,12 @@ struct CompScrollerVisual : winrt::implements<
12631299
winrt::event<winrt::Windows::Foundation::EventHandler<
12641300
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
12651301
m_scrollEndDragEvent;
1302+
winrt::event<winrt::Windows::Foundation::EventHandler<
1303+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
1304+
m_scrollMomentumBeginEvent;
1305+
winrt::event<winrt::Windows::Foundation::EventHandler<
1306+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
1307+
m_scrollMomentumEndEvent;
12661308
typename TTypeRedirects::SpriteVisual m_visual{nullptr};
12671309
typename TTypeRedirects::SpriteVisual m_contentVisual{nullptr};
12681310
typename TTypeRedirects::InteractionTracker m_interactionTracker{nullptr};

vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,32 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComp
13541354
}
13551355
});
13561356

1357+
m_scrollMomentumBeginRevoker = m_scrollVisual.ScrollMomentumBegin(
1358+
winrt::auto_revoke,
1359+
[this](
1360+
winrt::IInspectable const & /*sender*/,
1361+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
1362+
auto eventEmitter = GetEventEmitter();
1363+
if (eventEmitter) {
1364+
auto scrollMetrics = getScrollMetrics(eventEmitter, args);
1365+
std::static_pointer_cast<facebook::react::ScrollViewEventEmitter const>(eventEmitter)
1366+
->onMomentumScrollBegin(scrollMetrics);
1367+
}
1368+
});
1369+
1370+
m_scrollMomentumEndRevoker = m_scrollVisual.ScrollMomentumEnd(
1371+
winrt::auto_revoke,
1372+
[this](
1373+
winrt::IInspectable const & /*sender*/,
1374+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
1375+
auto eventEmitter = GetEventEmitter();
1376+
if (eventEmitter) {
1377+
auto scrollMetrics = getScrollMetrics(eventEmitter, args);
1378+
std::static_pointer_cast<facebook::react::ScrollViewEventEmitter const>(eventEmitter)
1379+
->onMomentumScrollEnd(scrollMetrics);
1380+
}
1381+
});
1382+
13571383
return visual;
13581384
}
13591385

vnext/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,12 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
148148
m_scrollPositionChangedRevoker{};
149149
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollBeginDrag_revoker
150150
m_scrollBeginDragRevoker{};
151-
152151
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollEndDrag_revoker
153152
m_scrollEndDragRevoker{};
153+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollMomentumBegin_revoker
154+
m_scrollMomentumBeginRevoker{};
155+
winrt::Microsoft::ReactNative::Composition::Experimental::IScrollVisual::ScrollMomentumEnd_revoker
156+
m_scrollMomentumEndRevoker{};
154157

155158
float m_zoomFactor{1.0f};
156159
bool m_isScrollingFromInertia = false;

0 commit comments

Comments
 (0)