Skip to content

Commit 7e9d145

Browse files
committed
feat: add allowsKeyboardScrolling prop to ScrollView for native api support
1 parent 52d87f9 commit 7e9d145

12 files changed

Lines changed: 104 additions & 13 deletions

File tree

packages/react-native/Libraries/Components/ScrollView/ScrollView.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,13 @@ interface ScrollResponderMixin extends SubscribableMixin {
334334
}
335335

336336
export interface ScrollViewPropsIOS {
337+
/**
338+
* When true, the scroll view allows scrolling its content with hardware
339+
* keyboard input. The default value is true. Available on iOS 17 and later.
340+
* @platform ios
341+
* @see https://developer.apple.com/documentation/uikit/uiscrollview/allowskeyboardscrolling
342+
*/
343+
allowsKeyboardScrolling?: boolean | undefined;
337344
/**
338345
* When true the scroll view bounces horizontally when it reaches the end
339346
* even if the content is smaller than the scroll view itself. The default

packages/react-native/Libraries/Components/ScrollView/ScrollView.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,13 @@ export interface PublicScrollViewInstance
175175
type InnerViewInstance = React.ElementRef<typeof View>;
176176

177177
export type ScrollViewPropsIOS = Readonly<{
178+
/**
179+
* When true, the scroll view allows scrolling its content with hardware
180+
* keyboard input. The default value is true. Available on iOS 17 and later.
181+
* @platform ios
182+
* @see https://developer.apple.com/documentation/uikit/uiscrollview/allowskeyboardscrolling
183+
*/
184+
allowsKeyboardScrolling?: boolean,
178185
/**
179186
* Controls whether iOS should automatically adjust the content inset
180187
* for scroll views that are placed behind a navigation bar or
@@ -1769,6 +1776,7 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
17691776
} = this.props;
17701777
const props = {
17711778
...otherProps,
1779+
allowsKeyboardScrolling: this.props.allowsKeyboardScrolling !== false,
17721780
alwaysBounceHorizontal,
17731781
alwaysBounceVertical,
17741782
style: StyleSheet.compose(baseStyle, this.props.style),

packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponent.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
104104
},
105105
},
106106
validAttributes: {
107+
allowsKeyboardScrolling: true,
107108
alwaysBounceHorizontal: true,
108109
alwaysBounceVertical: true,
109110
automaticallyAdjustContentInsets: true,

packages/react-native/Libraries/Components/ScrollView/ScrollViewNativeComponentType.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import type {ViewProps} from '../View/ViewPropTypes';
2121

2222
export type ScrollViewNativeProps = Readonly<{
2323
...ViewProps,
24+
allowsKeyboardScrolling?: ?boolean,
2425
alwaysBounceHorizontal?: ?boolean,
2526
alwaysBounceVertical?: ?boolean,
2627
automaticallyAdjustContentInsets?: ?boolean,

packages/react-native/React/Fabric/Mounting/ComponentViews/ScrollView/RCTScrollViewComponentView.mm

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,11 @@ - (instancetype)initWithFrame:(CGRect)frame
143143
_scrollView.clipsToBounds = _props->getClipsContentToBounds();
144144
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
145145
_scrollView.delaysContentTouches = NO;
146+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */
147+
if (@available(iOS 17.0, *)) {
148+
_scrollView.allowsKeyboardScrolling = YES;
149+
}
150+
#endif
146151
((RCTEnhancedScrollView *)_scrollView).overridingDelegate = self;
147152
_isUserTriggeredScrolling = NO;
148153
_shouldUpdateContentInsetAdjustmentBehavior = YES;
@@ -447,6 +452,14 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
447452
scrollView.keyboardDismissMode = RCTUIKeyboardDismissModeFromProps(newScrollViewProps);
448453
}
449454

455+
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */
456+
if (@available(iOS 17.0, *)) {
457+
if (oldScrollViewProps.allowsKeyboardScrolling != newScrollViewProps.allowsKeyboardScrolling) {
458+
scrollView.allowsKeyboardScrolling = newScrollViewProps.allowsKeyboardScrolling;
459+
}
460+
}
461+
#endif
462+
450463
[super updateProps:props oldProps:oldProps];
451464
}
452465

packages/react-native/React/Views/ScrollView/RCTScrollView.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,11 @@ - (void)updateClippedSubviews
540540
}
541541
}
542542

543+
- (void)setAllowsKeyboardScrolling:(BOOL)allowsKeyboardScrolling API_AVAILABLE(ios(17.0))
544+
{
545+
_scrollView.allowsKeyboardScrolling = allowsKeyboardScrolling;
546+
}
547+
543548
- (void)setContentInset:(UIEdgeInsets)contentInset
544549
{
545550
if (UIEdgeInsetsEqualToEdgeInsets(contentInset, _contentInset)) {

packages/react-native/React/Views/ScrollView/RCTScrollViewManager.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ - (UIView *)view
104104
RCT_EXPORT_VIEW_PROPERTY(inverted, BOOL)
105105
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustsScrollIndicatorInsets, BOOL)
106106
RCT_EXPORT_VIEW_PROPERTY(contentInsetAdjustmentBehavior, UIScrollViewContentInsetAdjustmentBehavior)
107+
RCT_EXPORT_VIEW_PROPERTY(allowsKeyboardScrolling, BOOL)
107108

108109
// overflow is used both in css-layout as well as by react-native. In css-layout
109110
// we always want to treat overflow as scroll but depending on what the overflow

packages/react-native/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,16 @@ BaseScrollViewProps::BaseScrollViewProps(
372372
rawProps,
373373
"isInvertedVirtualizedList",
374374
sourceProps.isInvertedVirtualizedList,
375-
{})) {}
375+
{})),
376+
allowsKeyboardScrolling(
377+
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
378+
? sourceProps.allowsKeyboardScrolling
379+
: convertRawProp(
380+
context,
381+
rawProps,
382+
"allowsKeyboardScrolling",
383+
sourceProps.allowsKeyboardScrolling,
384+
(Float)1.0)){}
376385

377386
void BaseScrollViewProps::setProp(
378387
const PropsParserContext& context,
@@ -425,6 +434,7 @@ void BaseScrollViewProps::setProp(
425434
RAW_SET_PROP_SWITCH_CASE_BASIC(contentInsetAdjustmentBehavior);
426435
RAW_SET_PROP_SWITCH_CASE_BASIC(scrollToOverflowEnabled);
427436
RAW_SET_PROP_SWITCH_CASE_BASIC(isInvertedVirtualizedList);
437+
RAW_SET_PROP_SWITCH_CASE_BASIC(allowsKeyboardScrolling);
428438
}
429439
}
430440

@@ -559,7 +569,11 @@ SharedDebugStringConvertibleList BaseScrollViewProps::getDebugProps() const {
559569
debugStringConvertibleItem(
560570
"isInvertedVirtualizedList",
561571
isInvertedVirtualizedList,
562-
defaultScrollViewProps.isInvertedVirtualizedList)};
572+
defaultScrollViewProps.isInvertedVirtualizedList),
573+
debugStringConvertibleItem(
574+
"allowsKeyboardScrolling",
575+
allowsKeyboardScrolling,
576+
defaultScrollViewProps.allowsKeyboardScrolling)};
563577
}
564578
#endif
565579

packages/react-native/ReactCommon/react/renderer/components/scrollview/BaseScrollViewProps.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class BaseScrollViewProps : public ViewProps {
6868
ContentInsetAdjustmentBehavior contentInsetAdjustmentBehavior{ContentInsetAdjustmentBehavior::Never};
6969
bool scrollToOverflowEnabled{false};
7070
bool isInvertedVirtualizedList{false};
71+
bool allowsKeyboardScrolling{true};
7172

7273
#pragma mark - DebugStringConvertible
7374

packages/react-native/ReactCommon/react/renderer/components/scrollview/platform/android/react/renderer/components/scrollview/HostPlatformScrollViewProps.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,10 @@ folly::dynamic HostPlatformScrollViewProps::getDiffProps(
316316
result["snapToInterval"] = snapToInterval;
317317
}
318318

319+
if (allowsKeyboardScrolling != oldProps->allowsKeyboardScrolling) {
320+
result["allowsKeyboardScrolling"] = allowsKeyboardScrolling;
321+
}
322+
319323
if (snapToAlignment != oldProps->snapToAlignment) {
320324
switch (snapToAlignment) {
321325
case ScrollViewSnapToAlignment::Start:

0 commit comments

Comments
 (0)