Skip to content

Commit 34e2fc4

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

11 files changed

Lines changed: 86 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/ReactNativeApi.d.ts

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* This source code is licensed under the MIT license found in the
55
* LICENSE file in the root directory of this source tree.
66
*
7-
* @generated SignedSource<<1c8637ab03a5fec9d39704d1ae305595>>
7+
* @generated SignedSource<<f8ef5ca5735af61732089661dee40517>>
88
*
99
* This file was generated by scripts/js-api/build-types/index.js.
1010
*/
@@ -4505,6 +4505,7 @@ declare interface ScrollViewImperativeMethods {
45054505
declare type ScrollViewNativeComponent = typeof $$ScrollViewNativeComponent
45064506
declare type ScrollViewNativeProps = Readonly<
45074507
Omit<ViewProps, "onResponderGrant"> & {
4508+
allowsKeyboardScrolling?: boolean
45084509
alwaysBounceHorizontal?: boolean
45094510
alwaysBounceVertical?: boolean
45104511
automaticallyAdjustContentInsets?: boolean
@@ -4588,6 +4589,7 @@ declare type ScrollViewPropsAndroid = {
45884589
readonly scrollsChildToFocus?: boolean
45894590
}
45904591
declare type ScrollViewPropsIOS = {
4592+
readonly allowsKeyboardScrolling?: boolean
45914593
readonly alwaysBounceHorizontal?: boolean
45924594
readonly alwaysBounceVertical?: boolean
45934595
readonly automaticallyAdjustContentInsets?: boolean
@@ -6064,7 +6066,7 @@ export {
60646066
AlertOptions, // a0cdac0f
60656067
AlertType, // 5ab91217
60666068
AndroidKeyboardEvent, // e03becc8
6067-
Animated, // 0652b5d1
6069+
Animated, // 52117bcb
60686070
AppConfig, // ce4209a7
60696071
AppRegistry, // 5edf0524
60706072
AppState, // 12012be5
@@ -6111,8 +6113,8 @@ export {
61116113
EventSubscription, // b8d084aa
61126114
ExtendedExceptionData, // 5a6ccf5a
61136115
FilterFunction, // bf24c0e3
6114-
FlatList, // 8c50f04a
6115-
FlatListProps, // e170f2c9
6116+
FlatList, // 39da788d
6117+
FlatListProps, // 12e2c439
61166118
FocusEvent, // 62fc1eb8
61176119
FontVariant, // 7c7558bb
61186120
GestureResponderEvent, // f693e9a5
@@ -6249,16 +6251,16 @@ export {
62496251
ScrollEvent, // 5d529218
62506252
ScrollResponderType, // c6860ec8
62516253
ScrollToLocationParamsType, // d7ecdad1
6252-
ScrollView, // a3918d1a
6254+
ScrollView, // 147623b2
62536255
ScrollViewImperativeMethods, // 7cd8d8de
6254-
ScrollViewProps, // 429fdd65
6256+
ScrollViewProps, // f25d7fbd
62556257
ScrollViewPropsAndroid, // 44210553
6256-
ScrollViewPropsIOS, // b34b696c
6258+
ScrollViewPropsIOS, // bf4b8a52
62576259
ScrollViewScrollToOptions, // 3313411e
62586260
SectionBase, // b376bddc
6259-
SectionList, // 92031230
6261+
SectionList, // a1b818ef
62606262
SectionListData, // 119baf83
6261-
SectionListProps, // c0d0a46a
6263+
SectionListProps, // 7b5b438c
62626264
SectionListRenderItem, // 1fad0435
62636265
SectionListRenderItemInfo, // 745e1992
62646266
Separators, // 6a45f7e3
@@ -6323,9 +6325,9 @@ export {
63236325
ViewStyle, // 00a0f8fb
63246326
VirtualViewMode, // 6be59722
63256327
VirtualizedList, // 68c7345e
6326-
VirtualizedListProps, // c7e8e7d7
6328+
VirtualizedListProps, // 161a7bb2
63276329
VirtualizedSectionList, // 9fd9cd61
6328-
VirtualizedSectionListProps, // 53a7e6a4
6330+
VirtualizedSectionListProps, // a9c5ff7e
63296331
WrapperComponentProvider, // 9cf3844c
63306332
codegenNativeCommands, // 628a7c0a
63316333
codegenNativeComponent, // 2baac257

0 commit comments

Comments
 (0)