2727
2828namespace Microsoft ::ReactNative::Composition::Experimental {
2929
30+ using namespace winrt ::Microsoft::ReactNative::Composition::Experimental;
31+
3032template <typename TSpriteVisual>
3133struct CompositionTypeTraits {};
3234
@@ -709,50 +711,24 @@ struct CompScrollerVisual : winrt::implements<
709711 void IdleStateEntered (
710712 typename TTypeRedirects::InteractionTracker sender,
711713 typename TTypeRedirects::InteractionTrackerIdleStateEnteredArgs args) noexcept {
712- // If we were in inertia and are now idle, momentum has ended
713- if (m_outer->m_inertia ) {
714- m_outer->FireScrollMomentumEnd ({sender.Position ().x , sender.Position ().y });
715- }
716-
717- // If we were interacting but never entered inertia (Interacting -> Idle),
718- // and the interaction was user-driven (requestId == 0), fire end-drag here.
719- // Note: if the interactionRequestId was non-zero it was caused by a Try* call
720- // (programmatic), so we should not fire onScrollEndDrag.
721- if (m_outer->m_interacting && args.RequestId () == 0 ) {
722- m_outer->FireScrollEndDrag ({sender.Position ().x , sender.Position ().y });
723- }
724-
725- // Clear state flags
726714 m_outer->m_custom = false ;
727715 m_outer->m_inertia = false ;
728- m_outer->m_interacting = false ;
729716 }
730717 void InertiaStateEntered (
731718 typename TTypeRedirects::InteractionTracker sender,
732719 typename TTypeRedirects::InteractionTrackerInertiaStateEnteredArgs args) noexcept {
733720 m_outer->m_custom = false ;
734721 m_outer->m_inertia = true ;
735722 m_outer->m_currentPosition = args.NaturalRestingPosition ();
736-
737- if (!m_outer->m_interacting && args.RequestId () == 0 ) {
738- m_outer->FireScrollBeginDrag ({args.NaturalRestingPosition ().x , args.NaturalRestingPosition ().y });
739- }
740-
741- // If interaction was user-driven (requestId == 0),
742- // fire ScrollEndDrag here (Interacting -> Inertia caused by user lift).
743- if (m_outer->m_interacting && args.RequestId () == 0 ) {
744- m_outer->FireScrollEndDrag ({args.NaturalRestingPosition ().x , args.NaturalRestingPosition ().y });
745- }
746-
747- // Fire momentum scroll begin when we enter inertia (user or programmatic)
748- m_outer->FireScrollMomentumBegin ({args.NaturalRestingPosition ().x , args.NaturalRestingPosition ().y });
723+ // When the user stops interacting with the object, tracker can go into two paths:
724+ // 1. tracker goes into idle state immediately
725+ // 2. tracker has just started gliding into Inertia state
726+ // Fire ScrollEndDrag
727+ m_outer->FireScrollEndDrag ({args.NaturalRestingPosition ().x , args.NaturalRestingPosition ().y });
749728 }
750729 void InteractingStateEntered (
751730 typename TTypeRedirects::InteractionTracker sender,
752731 typename TTypeRedirects::InteractionTrackerInteractingStateEnteredArgs args) noexcept {
753- // Mark that we're now interacting and remember the requestId (user manipulations => 0)
754- m_outer->m_interacting = true ;
755-
756732 // Fire when the user starts dragging the object
757733 m_outer->FireScrollBeginDrag ({sender.Position ().x , sender.Position ().y });
758734 }
@@ -762,10 +738,6 @@ struct CompScrollerVisual : winrt::implements<
762738 void ValuesChanged (
763739 typename TTypeRedirects::InteractionTracker sender,
764740 typename TTypeRedirects::InteractionTrackerValuesChangedArgs args) noexcept {
765- if (!m_outer->m_interacting && args.RequestId () == 0 ) {
766- m_outer->FireScrollBeginDrag ({args.Position ().x , args.Position ().y });
767- }
768- m_outer->m_interacting = true ;
769741 m_outer->m_currentPosition = args.Position ();
770742 m_outer->FireScrollPositionChanged ({args.Position ().x , args.Position ().y });
771743 }
@@ -901,9 +873,11 @@ struct CompScrollerVisual : winrt::implements<
901873 void SetSnapPoints (
902874 bool snapToStart,
903875 bool snapToEnd,
904- winrt::Windows::Foundation::Collections::IVectorView<float > const &offsets) noexcept {
876+ winrt::Windows::Foundation::Collections::IVectorView<float > const &offsets,
877+ SnapAlignment snapToAlignment) noexcept {
905878 m_snapToStart = snapToStart;
906879 m_snapToEnd = snapToEnd;
880+ m_snapToAlignment = snapToAlignment;
907881 m_snapToOffsets.clear ();
908882 if (offsets) {
909883 for (auto const &offset : offsets) {
@@ -1011,20 +985,6 @@ struct CompScrollerVisual : winrt::implements<
1011985 return m_scrollEndDragEvent.add (handler);
1012986 }
1013987
1014- winrt::event_token ScrollMomentumBegin (
1015- winrt::Windows::Foundation::EventHandler<
1016- winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs> const
1017- &handler) noexcept {
1018- return m_scrollMomentumBeginEvent.add (handler);
1019- }
1020-
1021- winrt::event_token ScrollMomentumEnd (
1022- winrt::Windows::Foundation::EventHandler<
1023- winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs> const
1024- &handler) noexcept {
1025- return m_scrollMomentumEndEvent.add (handler);
1026- }
1027-
1028988 void ScrollPositionChanged (winrt::event_token const &token) noexcept {
1029989 m_scrollPositionChangedEvent.remove (token);
1030990 }
@@ -1037,14 +997,6 @@ struct CompScrollerVisual : winrt::implements<
1037997 m_scrollEndDragEvent.remove (token);
1038998 }
1039999
1040- void ScrollMomentumBegin (winrt::event_token const &token) noexcept {
1041- m_scrollMomentumBeginEvent.remove (token);
1042- }
1043-
1044- void ScrollMomentumEnd (winrt::event_token const &token) noexcept {
1045- m_scrollMomentumEndEvent.remove (token);
1046- }
1047-
10481000 void ContentSize (winrt::Windows::Foundation::Numerics::float2 const &size) noexcept {
10491001 m_contentSize = size;
10501002 m_contentVisual.Size (size);
@@ -1123,14 +1075,6 @@ struct CompScrollerVisual : winrt::implements<
11231075 m_scrollEndDragEvent (*this , winrt::make<CompScrollPositionChangedArgs>(position));
11241076 }
11251077
1126- void FireScrollMomentumBegin (winrt::Windows::Foundation::Numerics::float2 position) noexcept {
1127- m_scrollMomentumBeginEvent (*this , winrt::make<CompScrollPositionChangedArgs>(position));
1128- }
1129-
1130- void FireScrollMomentumEnd (winrt::Windows::Foundation::Numerics::float2 position) noexcept {
1131- m_scrollMomentumEndEvent (*this , winrt::make<CompScrollPositionChangedArgs>(position));
1132- }
1133-
11341078 void UpdateMaxPosition () noexcept {
11351079 m_interactionTracker.MaxPosition (
11361080 {std::max<float >(m_contentSize.x - m_visualSize.x , 0 ),
@@ -1160,6 +1104,22 @@ struct CompScrollerVisual : winrt::implements<
11601104 }
11611105
11621106 snapPositions.insert (snapPositions.end (), m_snapToOffsets.begin (), m_snapToOffsets.end ());
1107+
1108+ // Adjust snap positions based on alignment
1109+ const float viewportSize = m_horizontal ? visualSize.x : visualSize.y ;
1110+ if (m_snapToAlignment == SnapAlignment::Center) {
1111+ // For center alignment, offset snap positions by half the viewport size
1112+ for (auto &position : snapPositions) {
1113+ position = std::max (0 .0f , position - viewportSize / 2 .0f );
1114+ }
1115+ } else if (m_snapToAlignment == SnapAlignment::End) {
1116+ // For end alignment, offset snap positions by the full viewport size
1117+ for (auto &position : snapPositions) {
1118+ position = std::max (0 .0f , position - viewportSize);
1119+ }
1120+ }
1121+ // For Start alignment, no adjustment needed
1122+
11631123 std::sort (snapPositions.begin (), snapPositions.end ());
11641124 snapPositions.erase (std::unique (snapPositions.begin (), snapPositions.end ()), snapPositions.end ());
11651125
@@ -1287,9 +1247,9 @@ struct CompScrollerVisual : winrt::implements<
12871247 bool m_snapToStart{true };
12881248 bool m_snapToEnd{true };
12891249 std::vector<float > m_snapToOffsets;
1250+ SnapAlignment m_snapToAlignment{SnapAlignment::Start};
12901251 bool m_inertia{false };
12911252 bool m_custom{false };
1292- bool m_interacting{false };
12931253 winrt::Windows::Foundation::Numerics::float3 m_targetPosition;
12941254 winrt::Windows::Foundation::Numerics::float3 m_currentPosition;
12951255 winrt::Windows::Foundation::Numerics::float2 m_contentSize{0 };
@@ -1303,12 +1263,6 @@ struct CompScrollerVisual : winrt::implements<
13031263 winrt::event<winrt::Windows::Foundation::EventHandler<
13041264 winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
13051265 m_scrollEndDragEvent;
1306- winrt::event<winrt::Windows::Foundation::EventHandler<
1307- winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
1308- m_scrollMomentumBeginEvent;
1309- winrt::event<winrt::Windows::Foundation::EventHandler<
1310- winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs>>
1311- m_scrollMomentumEndEvent;
13121266 typename TTypeRedirects::SpriteVisual m_visual{nullptr };
13131267 typename TTypeRedirects::SpriteVisual m_contentVisual{nullptr };
13141268 typename TTypeRedirects::InteractionTracker m_interactionTracker{nullptr };
0 commit comments