Skip to content

Commit 9da1297

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

14 files changed

Lines changed: 105 additions & 11 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/Libraries/Components/ScrollView/__tests__/__snapshots__/ScrollView-test.js.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ exports[`ScrollView renders its children: should deep render when mocked (please
1414

1515
exports[`ScrollView renders its children: should deep render when not mocked (please verify output manually) 1`] = `
1616
<RCTScrollView
17+
allowsKeyboardScrolling={true}
1718
alwaysBounceVertical={true}
1819
onContentSizeChange={null}
1920
onLayout={[Function]}

packages/react-native/Libraries/Lists/__tests__/__snapshots__/FlatList-test.js.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
exports[`FlatList ignores invalid data 1`] = `
44
<RCTScrollView
5+
allowsKeyboardScrolling={true}
56
alwaysBounceVertical={true}
67
data={123456}
78
getItem={[Function]}
@@ -184,6 +185,7 @@ exports[`FlatList renders all the bells and whistles 1`] = `
184185

185186
exports[`FlatList renders array-like data 1`] = `
186187
<RCTScrollView
188+
allowsKeyboardScrolling={true}
187189
alwaysBounceVertical={true}
188190
data={
189191
Object {

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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,15 @@ BaseScrollViewProps::BaseScrollViewProps(
2222
const BaseScrollViewProps& sourceProps,
2323
const RawProps& rawProps)
2424
: ViewProps(context, sourceProps, rawProps),
25+
allowsKeyboardScrolling(
26+
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
27+
? sourceProps.allowsKeyboardScrolling
28+
: convertRawProp(
29+
context,
30+
rawProps,
31+
"allowsKeyboardScrolling",
32+
sourceProps.allowsKeyboardScrolling,
33+
{})),
2534
alwaysBounceHorizontal(
2635
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
2736
? sourceProps.alwaysBounceHorizontal
@@ -387,6 +396,7 @@ void BaseScrollViewProps::setProp(
387396
static auto defaults = BaseScrollViewProps{};
388397

389398
switch (hash) {
399+
RAW_SET_PROP_SWITCH_CASE_BASIC(allowsKeyboardScrolling);
390400
RAW_SET_PROP_SWITCH_CASE_BASIC(alwaysBounceHorizontal);
391401
RAW_SET_PROP_SWITCH_CASE_BASIC(alwaysBounceVertical);
392402
RAW_SET_PROP_SWITCH_CASE_BASIC(bounces);
@@ -436,6 +446,10 @@ SharedDebugStringConvertibleList BaseScrollViewProps::getDebugProps() const {
436446

437447
return ViewProps::getDebugProps() +
438448
SharedDebugStringConvertibleList{
449+
debugStringConvertibleItem(
450+
"allowsKeyboardScrolling",
451+
allowsKeyboardScrolling,
452+
defaultScrollViewProps.allowsKeyboardScrolling),
439453
debugStringConvertibleItem(
440454
"alwaysBounceHorizontal",
441455
alwaysBounceHorizontal,

0 commit comments

Comments
 (0)