@@ -871,8 +871,13 @@ void ScrollViewComponentView::updateContentVisualSize() noexcept {
871871 m_horizontalScrollbarComponent->ContentSize (contentSize);
872872 m_scrollVisual.ContentSize (contentSize);
873873
874- // Update snap points if snapToInterval is being used, as content size affects the number of snap points
875- updateSnapPoints ();
874+ // TODO: For optimal performance, snapToInterval should use InteractionTrackerInertiaRestingValue
875+ // with expression animations (similar to snapToEnd implementation) to avoid recalculating
876+ // all snap points on content size changes. For now, only update when actually needed.
877+ const auto &viewProps = *std::static_pointer_cast<const facebook::react::ScrollViewProps>(this ->viewProps ());
878+ if (viewProps.snapToInterval > 0 && viewProps.snapToOffsets .size () == 0 ) {
879+ updateSnapPointsForInterval ();
880+ }
876881}
877882
878883void ScrollViewComponentView::prepareForRecycle () noexcept {}
@@ -1457,25 +1462,49 @@ void ScrollViewComponentView::updateSnapPoints() noexcept {
14571462 snapToOffsets.Append (static_cast <float >(offset));
14581463 }
14591464 } else if (viewProps.snapToInterval > 0 ) {
1460- // Generate snap points based on interval
1461- // Calculate the content size to determine how many intervals to create
1462- float contentLength = viewProps.horizontal
1463- ? std::max (m_contentSize.width , m_layoutMetrics.frame .size .width ) * m_layoutMetrics.pointScaleFactor
1464- : std::max (m_contentSize.height , m_layoutMetrics.frame .size .height ) * m_layoutMetrics.pointScaleFactor ;
1465-
1466- float interval = static_cast <float >(viewProps.snapToInterval ) * m_layoutMetrics.pointScaleFactor ;
1467-
1468- // Ensure we have a reasonable minimum interval to avoid infinite loops or excessive memory usage
1469- if (interval >= 1 .0f && contentLength > 0 ) {
1470- // Generate offsets at each interval, but limit the number of snap points to avoid excessive memory usage
1471- const int maxSnapPoints = 1000 ; // Reasonable limit
1472- int snapPointCount = 0 ;
1473-
1474- for (float offset = 0 ; offset <= contentLength && snapPointCount < maxSnapPoints; offset += interval) {
1475- snapToOffsets.Append (offset);
1476- snapPointCount++;
1477- }
1478- }
1465+ // For snapToInterval, delegate to specialized method
1466+ updateSnapPointsForInterval ();
1467+ return ;
1468+ }
1469+
1470+ m_scrollVisual.SetSnapPoints (viewProps.snapToStart , viewProps.snapToEnd , snapToOffsets.GetView ());
1471+ }
1472+
1473+ void ScrollViewComponentView::updateSnapPointsForInterval () noexcept {
1474+ const auto &viewProps = *std::static_pointer_cast<const facebook::react::ScrollViewProps>(this ->viewProps ());
1475+
1476+ if (viewProps.snapToInterval <= 0 ) {
1477+ return ;
1478+ }
1479+
1480+ const auto snapToOffsets = winrt::single_threaded_vector<float >();
1481+ float interval = static_cast <float >(viewProps.snapToInterval ) * m_layoutMetrics.pointScaleFactor ;
1482+
1483+ if (interval < 1 .0f ) {
1484+ return ;
1485+ }
1486+
1487+ // Calculate the content size
1488+ float contentLength = viewProps.horizontal
1489+ ? std::max (m_contentSize.width , m_layoutMetrics.frame .size .width ) * m_layoutMetrics.pointScaleFactor
1490+ : std::max (m_contentSize.height , m_layoutMetrics.frame .size .height ) * m_layoutMetrics.pointScaleFactor ;
1491+
1492+ if (contentLength <= 0 ) {
1493+ return ;
1494+ }
1495+
1496+ // Performance optimization: Instead of generating all possible snap points,
1497+ // generate a reasonable number based on the current viewport and content size.
1498+ // The composition system's InteractionTrackerInertiaRestingValue would be ideal
1499+ // for true dynamic calculation, but requires interface changes.
1500+
1501+ const int maxSnapPoints = 500 ; // Reduced from 1000 for better performance
1502+ int snapPointCount = 0 ;
1503+
1504+ // Generate snap points across the entire content length
1505+ for (float offset = 0 ; offset <= contentLength && snapPointCount < maxSnapPoints; offset += interval) {
1506+ snapToOffsets.Append (offset);
1507+ snapPointCount++;
14791508 }
14801509
14811510 m_scrollVisual.SetSnapPoints (viewProps.snapToStart , viewProps.snapToEnd , snapToOffsets.GetView ());
0 commit comments