From 45b1aef291d26c5749ad8391582d3eb1146dcdda Mon Sep 17 00:00:00 2001 From: Zhengwei Liu Date: Wed, 14 Feb 2024 18:24:46 -0800 Subject: [PATCH] introduce experimental props endDraggingSensitivityMultiplier and endDraggingSensitivityVelocityMultiplier to ScrollView Summary: changelog: [internal] Adding experimental props to control scroll speed on iOS. Reviewed By: cipolleschi Differential Revision: D53757152 fbshipit-source-id: 5848780ffcc91242494d371731cc0efce87b3159 --- .../ScrollView/RCTScrollViewComponentView.mm | 22 +++++++++++++++++++ .../Views/ScrollView/RCTScrollViewManager.m | 2 ++ .../components/scrollview/ScrollViewProps.cpp | 18 +++++++++++++++ .../components/scrollview/ScrollViewProps.h | 2 ++ 4 files changed, 44 insertions(+) diff --git a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm index 7bc047c740ab33..90a9a134dcea72 100644 --- a/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm +++ b/packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm @@ -105,6 +105,9 @@ @implementation RCTScrollViewComponentView { CGRect _prevFirstVisibleFrame; __weak UIView *_firstVisibleView; + + CGFloat _endDraggingSensitivityMultiplier; + CGFloat _endDraggingSensitivityVelocityMultiplier; } + (RCTScrollViewComponentView *_Nullable)findScrollViewComponentViewForView:(UIView *)view @@ -134,6 +137,8 @@ - (instancetype)initWithFrame:(CGRect)frame [self.scrollViewDelegateSplitter addDelegate:self]; _scrollEventThrottle = 0; + _endDraggingSensitivityVelocityMultiplier = 0; + _endDraggingSensitivityMultiplier = 1; } return self; @@ -230,6 +235,9 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared & _scrollView.indicatorStyle = RCTUIScrollViewIndicatorStyleFromProps(newScrollViewProps); } + _endDraggingSensitivityMultiplier = newScrollViewProps.endDraggingSensitivityMultiplier; + _endDraggingSensitivityVelocityMultiplier = newScrollViewProps.endDraggingSensitivityVelocityMultiplier; + if (oldScrollViewProps.scrollEventThrottle != newScrollViewProps.scrollEventThrottle) { // Zero means "send value only once per significant logical event". // Prop value is in milliseconds. @@ -432,6 +440,20 @@ - (void)prepareForRecycle #pragma mark - UIScrollViewDelegate +- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView + withVelocity:(CGPoint)velocity + targetContentOffset:(inout CGPoint *)targetContentOffset +{ + if (fabs(_endDraggingSensitivityMultiplier - 1) > 0.0001f || + fabs(_endDraggingSensitivityVelocityMultiplier) > 0.0001f) { + if (targetContentOffset->y > 0) { + const CGFloat travel = targetContentOffset->y - scrollView.contentOffset.y; + targetContentOffset->y = scrollView.contentOffset.y + travel * _endDraggingSensitivityMultiplier + + velocity.y * _endDraggingSensitivityVelocityMultiplier; + } + } +} + - (BOOL)touchesShouldCancelInContentView:(__unused UIView *)view { // Historically, `UIScrollView`s in React Native do not cancel touches diff --git a/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m b/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m index 03355504e0a1dc..9ce23ade7c8c16 100644 --- a/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m +++ b/packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m @@ -68,6 +68,8 @@ - (UIView *)view RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustContentInsets, BOOL) RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustKeyboardInsets, BOOL) RCT_EXPORT_VIEW_PROPERTY(decelerationRate, CGFloat) +RCT_EXPORT_VIEW_PROPERTY(endDraggingSensitivityMultiplier, CGFloat) +RCT_EXPORT_VIEW_PROPERTY(endDraggingSensitivityVelocityMultiplier, CGFloat) RCT_EXPORT_VIEW_PROPERTY(directionalLockEnabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(indicatorStyle, UIScrollViewIndicatorStyle) RCT_EXPORT_VIEW_PROPERTY(keyboardDismissMode, UIScrollViewKeyboardDismissMode) diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp index 4bf5b3c038c2fb..19a44907658e32 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.cpp @@ -100,6 +100,24 @@ ScrollViewProps::ScrollViewProps( "decelerationRate", sourceProps.decelerationRate, (Float)0.998)), + endDraggingSensitivityMultiplier( + CoreFeatures::enablePropIteratorSetter + ? sourceProps.endDraggingSensitivityMultiplier + : convertRawProp( + context, + rawProps, + "endDraggingSensitivityMultiplier", + sourceProps.endDraggingSensitivityMultiplier, + 1)), + endDraggingSensitivityVelocityMultiplier( + CoreFeatures::enablePropIteratorSetter + ? sourceProps.endDraggingSensitivityVelocityMultiplier + : convertRawProp( + context, + rawProps, + "endDraggingSensitivityVelocityMultiplier", + sourceProps.endDraggingSensitivityVelocityMultiplier, + 0)), directionalLockEnabled( CoreFeatures::enablePropIteratorSetter ? sourceProps.directionalLockEnabled diff --git a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h index 18bd59d6d12ad2..2eb7465d6f3196 100644 --- a/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h +++ b/packages/react-native/ReactCommon/react/renderer/components/scrollview/ScrollViewProps.h @@ -41,6 +41,8 @@ class ScrollViewProps final : public ViewProps { bool automaticallyAdjustContentInsets{}; bool automaticallyAdjustsScrollIndicatorInsets{true}; Float decelerationRate{0.998f}; + Float endDraggingSensitivityMultiplier{1}; + Float endDraggingSensitivityVelocityMultiplier{0}; bool directionalLockEnabled{}; ScrollViewIndicatorStyle indicatorStyle{}; ScrollViewKeyboardDismissMode keyboardDismissMode{};