Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,13 @@ interface ScrollResponderMixin extends SubscribableMixin {
}

export interface ScrollViewPropsIOS {
/**
* When true, the scroll view allows scrolling its content with hardware
* keyboard input. The default value is true. Available on iOS 17 and later.
* @platform ios
* @see https://developer.apple.com/documentation/uikit/uiscrollview/allowskeyboardscrolling
*/
allowsKeyboardScrolling?: boolean | undefined;
/**
* When true the scroll view bounces horizontally when it reaches the end
* even if the content is smaller than the scroll view itself. The default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,13 @@ export interface PublicScrollViewInstance
type InnerViewInstance = React.ElementRef<typeof View>;

export type ScrollViewPropsIOS = Readonly<{
/**
* When true, the scroll view allows scrolling its content with hardware
* keyboard input. The default value is true. Available on iOS 17 and later.
* @platform ios
* @see https://developer.apple.com/documentation/uikit/uiscrollview/allowskeyboardscrolling
*/
allowsKeyboardScrolling?: boolean,
/**
* Controls whether iOS should automatically adjust the content inset
* for scroll views that are placed behind a navigation bar or
Expand Down Expand Up @@ -1769,6 +1776,7 @@ class ScrollView extends React.Component<ScrollViewProps, ScrollViewState> {
} = this.props;
const props = {
...otherProps,
allowsKeyboardScrolling: this.props.allowsKeyboardScrolling !== false,
alwaysBounceHorizontal,
alwaysBounceVertical,
style: StyleSheet.compose(baseStyle, this.props.style),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export const __INTERNAL_VIEW_CONFIG: PartialViewConfig =
},
},
validAttributes: {
allowsKeyboardScrolling: true,
alwaysBounceHorizontal: true,
alwaysBounceVertical: true,
automaticallyAdjustContentInsets: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import type {ViewProps} from '../View/ViewPropTypes';

export type ScrollViewNativeProps = Readonly<{
...ViewProps,
allowsKeyboardScrolling?: ?boolean,
alwaysBounceHorizontal?: ?boolean,
alwaysBounceVertical?: ?boolean,
automaticallyAdjustContentInsets?: ?boolean,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ exports[`ScrollView renders its children: should deep render when mocked (please

exports[`ScrollView renders its children: should deep render when not mocked (please verify output manually) 1`] = `
<RCTScrollView
allowsKeyboardScrolling={true}
alwaysBounceVertical={true}
onContentSizeChange={null}
onLayout={[Function]}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

exports[`FlatList ignores invalid data 1`] = `
<RCTScrollView
allowsKeyboardScrolling={true}
alwaysBounceVertical={true}
data={123456}
getItem={[Function]}
Expand Down Expand Up @@ -184,6 +185,7 @@ exports[`FlatList renders all the bells and whistles 1`] = `

exports[`FlatList renders array-like data 1`] = `
<RCTScrollView
allowsKeyboardScrolling={true}
alwaysBounceVertical={true}
data={
Object {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,11 @@ - (instancetype)initWithFrame:(CGRect)frame
_scrollView.clipsToBounds = _props->getClipsContentToBounds();
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
_scrollView.delaysContentTouches = NO;
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */
if (@available(iOS 17.0, *)) {
_scrollView.allowsKeyboardScrolling = YES;
}
#endif
((RCTEnhancedScrollView *)_scrollView).overridingDelegate = self;
_isUserTriggeredScrolling = NO;
_shouldUpdateContentInsetAdjustmentBehavior = YES;
Expand Down Expand Up @@ -447,6 +452,14 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
scrollView.keyboardDismissMode = RCTUIKeyboardDismissModeFromProps(newScrollViewProps);
}

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 170000 /* __IPHONE_17_0 */
if (@available(iOS 17.0, *)) {
if (oldScrollViewProps.allowsKeyboardScrolling != newScrollViewProps.allowsKeyboardScrolling) {
scrollView.allowsKeyboardScrolling = newScrollViewProps.allowsKeyboardScrolling;
}
}
#endif

[super updateProps:props oldProps:oldProps];
}

Expand Down
5 changes: 5 additions & 0 deletions packages/react-native/React/Views/ScrollView/RCTScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,11 @@ - (void)updateClippedSubviews
}
}

- (void)setAllowsKeyboardScrolling:(BOOL)allowsKeyboardScrolling API_AVAILABLE(ios(17.0))
{
_scrollView.allowsKeyboardScrolling = allowsKeyboardScrolling;
}

- (void)setContentInset:(UIEdgeInsets)contentInset
{
if (UIEdgeInsetsEqualToEdgeInsets(contentInset, _contentInset)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(inverted, BOOL)
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustsScrollIndicatorInsets, BOOL)
RCT_EXPORT_VIEW_PROPERTY(contentInsetAdjustmentBehavior, UIScrollViewContentInsetAdjustmentBehavior)
RCT_EXPORT_VIEW_PROPERTY(allowsKeyboardScrolling, BOOL)

// overflow is used both in css-layout as well as by react-native. In css-layout
// we always want to treat overflow as scroll but depending on what the overflow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,15 @@ BaseScrollViewProps::BaseScrollViewProps(
const BaseScrollViewProps& sourceProps,
const RawProps& rawProps)
: ViewProps(context, sourceProps, rawProps),
allowsKeyboardScrolling(
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
? sourceProps.allowsKeyboardScrolling
: convertRawProp(
context,
rawProps,
"allowsKeyboardScrolling",
sourceProps.allowsKeyboardScrolling,
{})),
alwaysBounceHorizontal(
ReactNativeFeatureFlags::enableCppPropsIteratorSetter()
? sourceProps.alwaysBounceHorizontal
Expand Down Expand Up @@ -387,6 +396,7 @@ void BaseScrollViewProps::setProp(
static auto defaults = BaseScrollViewProps{};

switch (hash) {
RAW_SET_PROP_SWITCH_CASE_BASIC(allowsKeyboardScrolling);
RAW_SET_PROP_SWITCH_CASE_BASIC(alwaysBounceHorizontal);
RAW_SET_PROP_SWITCH_CASE_BASIC(alwaysBounceVertical);
RAW_SET_PROP_SWITCH_CASE_BASIC(bounces);
Expand Down Expand Up @@ -436,6 +446,10 @@ SharedDebugStringConvertibleList BaseScrollViewProps::getDebugProps() const {

return ViewProps::getDebugProps() +
SharedDebugStringConvertibleList{
debugStringConvertibleItem(
"allowsKeyboardScrolling",
allowsKeyboardScrolling,
defaultScrollViewProps.allowsKeyboardScrolling),
debugStringConvertibleItem(
"alwaysBounceHorizontal",
alwaysBounceHorizontal,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class BaseScrollViewProps : public ViewProps {

#pragma mark - Props

bool allowsKeyboardScrolling{true};
bool alwaysBounceHorizontal{};
bool alwaysBounceVertical{};
bool bounces{true};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ folly::dynamic HostPlatformScrollViewProps::getDiffProps(

folly::dynamic result = ViewProps::getDiffProps(oldProps);

if (allowsKeyboardScrolling != oldProps->allowsKeyboardScrolling) {
result["allowsKeyboardScrolling"] = allowsKeyboardScrolling;
}

if (alwaysBounceHorizontal != oldProps->alwaysBounceHorizontal) {
result["alwaysBounceHorizontal"] = alwaysBounceHorizontal;
}
Expand Down
24 changes: 13 additions & 11 deletions packages/react-native/ReactNativeApi.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated SignedSource<<1c8637ab03a5fec9d39704d1ae305595>>
* @generated SignedSource<<f8ef5ca5735af61732089661dee40517>>
*
* This file was generated by scripts/js-api/build-types/index.js.
*/
Expand Down Expand Up @@ -4505,6 +4505,7 @@ declare interface ScrollViewImperativeMethods {
declare type ScrollViewNativeComponent = typeof $$ScrollViewNativeComponent
declare type ScrollViewNativeProps = Readonly<
Omit<ViewProps, "onResponderGrant"> & {
allowsKeyboardScrolling?: boolean
alwaysBounceHorizontal?: boolean
alwaysBounceVertical?: boolean
automaticallyAdjustContentInsets?: boolean
Expand Down Expand Up @@ -4588,6 +4589,7 @@ declare type ScrollViewPropsAndroid = {
readonly scrollsChildToFocus?: boolean
}
declare type ScrollViewPropsIOS = {
readonly allowsKeyboardScrolling?: boolean
readonly alwaysBounceHorizontal?: boolean
readonly alwaysBounceVertical?: boolean
readonly automaticallyAdjustContentInsets?: boolean
Expand Down Expand Up @@ -6064,7 +6066,7 @@ export {
AlertOptions, // a0cdac0f
AlertType, // 5ab91217
AndroidKeyboardEvent, // e03becc8
Animated, // 0652b5d1
Animated, // 52117bcb
AppConfig, // ce4209a7
AppRegistry, // 5edf0524
AppState, // 12012be5
Expand Down Expand Up @@ -6111,8 +6113,8 @@ export {
EventSubscription, // b8d084aa
ExtendedExceptionData, // 5a6ccf5a
FilterFunction, // bf24c0e3
FlatList, // 8c50f04a
FlatListProps, // e170f2c9
FlatList, // 39da788d
FlatListProps, // 12e2c439
FocusEvent, // 62fc1eb8
FontVariant, // 7c7558bb
GestureResponderEvent, // f693e9a5
Expand Down Expand Up @@ -6249,16 +6251,16 @@ export {
ScrollEvent, // 5d529218
ScrollResponderType, // c6860ec8
ScrollToLocationParamsType, // d7ecdad1
ScrollView, // a3918d1a
ScrollView, // 147623b2
ScrollViewImperativeMethods, // 7cd8d8de
ScrollViewProps, // 429fdd65
ScrollViewProps, // f25d7fbd
ScrollViewPropsAndroid, // 44210553
ScrollViewPropsIOS, // b34b696c
ScrollViewPropsIOS, // bf4b8a52
ScrollViewScrollToOptions, // 3313411e
SectionBase, // b376bddc
SectionList, // 92031230
SectionList, // a1b818ef
SectionListData, // 119baf83
SectionListProps, // c0d0a46a
SectionListProps, // 7b5b438c
SectionListRenderItem, // 1fad0435
SectionListRenderItemInfo, // 745e1992
Separators, // 6a45f7e3
Expand Down Expand Up @@ -6323,9 +6325,9 @@ export {
ViewStyle, // 00a0f8fb
VirtualViewMode, // 6be59722
VirtualizedList, // 68c7345e
VirtualizedListProps, // c7e8e7d7
VirtualizedListProps, // 161a7bb2
VirtualizedSectionList, // 9fd9cd61
VirtualizedSectionListProps, // 53a7e6a4
VirtualizedSectionListProps, // a9c5ff7e
WrapperComponentProvider, // 9cf3844c
codegenNativeCommands, // 628a7c0a
codegenNativeComponent, // 2baac257
Expand Down
34 changes: 34 additions & 0 deletions packages/rn-tester/js/examples/ScrollView/ScrollViewExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,14 @@ if (Platform.OS === 'ios') {
return <ScrollToOptions />;
},
});
examples.push({
title: '<ScrollView> allowsKeyboardScrolling\n',
description:
'When true, the scroll view allows scrolling its content with hardware keyboard input. The default value is true. Available on iOS 17 and later.',
render(): React.Node {
return <AllowsKeyboardScrollingExample />;
},
});
} else if (Platform.OS === 'android') {
examples.push({
title: '<ScrollView> EndFillColor & FadingEdgeLength\n',
Expand Down Expand Up @@ -610,6 +618,32 @@ const ScrollsChildToFocusExample = () => {
);
};

const AllowsKeyboardScrollingExample = () => {
const [allowsKeyboardScrolling, setAllowsKeyboardScrolling] = useState(true);
return (
<View>
<RNTesterText style={styles.text}>
Connect a hardware keyboard and use Page Up, Page Down, Home, or End
keys to scroll.
</RNTesterText>
<ScrollView
style={[styles.scrollView, {height: 200}]}
nestedScrollEnabled
allowsKeyboardScrolling={allowsKeyboardScrolling}>
<TextInput style={styles.textInput} placeholder="Focusable TextInput" />
{ITEMS.map(createItemRow)}
</ScrollView>
<Button
label={'allowsKeyboardScrolling: ' + allowsKeyboardScrolling.toString()}
onPress={() => setAllowsKeyboardScrolling(!allowsKeyboardScrolling)}
/>
<RNTesterText>
When false, hardware keyboard keys will not scroll the view.
</RNTesterText>
</View>
);
};

const HorizontalScrollView = (props: {
direction: 'ltr' | 'rtl',
itemCount?: number,
Expand Down
1 change: 1 addition & 0 deletions scripts/cxx-api/api-snapshots/ReactAndroidDebugCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -1668,6 +1668,7 @@ class facebook::react::BaseParagraphProps : public facebook::react::HostPlatform
class facebook::react::BaseScrollViewProps : public facebook::react::HostPlatformViewProps {
public BaseScrollViewProps() = default;
public BaseScrollViewProps(const facebook::react::PropsParserContext& context, const facebook::react::BaseScrollViewProps& sourceProps, const facebook::react::RawProps& rawProps);
public bool allowsKeyboardScrolling;
public bool alwaysBounceHorizontal;
public bool alwaysBounceVertical;
public bool automaticallyAdjustContentInsets;
Expand Down
1 change: 1 addition & 0 deletions scripts/cxx-api/api-snapshots/ReactAndroidReleaseCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -1666,6 +1666,7 @@ class facebook::react::BaseParagraphProps : public facebook::react::HostPlatform
class facebook::react::BaseScrollViewProps : public facebook::react::HostPlatformViewProps {
public BaseScrollViewProps() = default;
public BaseScrollViewProps(const facebook::react::PropsParserContext& context, const facebook::react::BaseScrollViewProps& sourceProps, const facebook::react::RawProps& rawProps);
public bool allowsKeyboardScrolling;
public bool alwaysBounceHorizontal;
public bool alwaysBounceVertical;
public bool automaticallyAdjustContentInsets;
Expand Down
1 change: 1 addition & 0 deletions scripts/cxx-api/api-snapshots/ReactAppleDebugCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -4618,6 +4618,7 @@ class facebook::react::BaseParagraphProps : public facebook::react::HostPlatform
class facebook::react::BaseScrollViewProps : public facebook::react::HostPlatformViewProps {
public BaseScrollViewProps() = default;
public BaseScrollViewProps(const facebook::react::PropsParserContext& context, const facebook::react::BaseScrollViewProps& sourceProps, const facebook::react::RawProps& rawProps);
public bool allowsKeyboardScrolling;
public bool alwaysBounceHorizontal;
public bool alwaysBounceVertical;
public bool automaticallyAdjustContentInsets;
Expand Down
1 change: 1 addition & 0 deletions scripts/cxx-api/api-snapshots/ReactAppleReleaseCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -4616,6 +4616,7 @@ class facebook::react::BaseParagraphProps : public facebook::react::HostPlatform
class facebook::react::BaseScrollViewProps : public facebook::react::HostPlatformViewProps {
public BaseScrollViewProps() = default;
public BaseScrollViewProps(const facebook::react::PropsParserContext& context, const facebook::react::BaseScrollViewProps& sourceProps, const facebook::react::RawProps& rawProps);
public bool allowsKeyboardScrolling;
public bool alwaysBounceHorizontal;
public bool alwaysBounceVertical;
public bool automaticallyAdjustContentInsets;
Expand Down
1 change: 1 addition & 0 deletions scripts/cxx-api/api-snapshots/ReactCommonDebugCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,7 @@ class facebook::react::BaseScrollViewProps : public facebook::react::HostPlatfor
public Float scrollEventThrottle;
public Float snapToInterval;
public Float zoomScale;
public bool allowsKeyboardScrolling;
public bool alwaysBounceHorizontal;
public bool alwaysBounceVertical;
public bool automaticallyAdjustContentInsets;
Expand Down
1 change: 1 addition & 0 deletions scripts/cxx-api/api-snapshots/ReactCommonReleaseCxx.api
Original file line number Diff line number Diff line change
Expand Up @@ -1001,6 +1001,7 @@ class facebook::react::BaseScrollViewProps : public facebook::react::HostPlatfor
public Float scrollEventThrottle;
public Float snapToInterval;
public Float zoomScale;
public bool allowsKeyboardScrolling;
public bool alwaysBounceHorizontal;
public bool alwaysBounceVertical;
public bool automaticallyAdjustContentInsets;
Expand Down
Loading