Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ScrollView.automaticallyAdjustsScrollIndicatorInsets prop (on iOS) #29809

Closed
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
6 changes: 6 additions & 0 deletions Libraries/Components/ScrollView/ScrollView.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,12 @@ type IOSProps = $ReadOnly<{|
* @platform ios
*/
automaticallyAdjustContentInsets?: ?boolean,
/**
* Controls whether iOS should automatically adjust the scroll indicator
* insets. The default value is true. Available on iOS 13 and later.
* @platform ios
*/
automaticallyAdjustsScrollIndicatorInsets?: ?boolean,
/**
* The amount by which the scroll view content is inset from the edges
* of the scroll view. Defaults to `{top: 0, left: 0, bottom: 0, right: 0}`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ const ScrollViewNativeComponent: HostComponent<Props> = NativeComponentRegistry.
alwaysBounceHorizontal: true,
alwaysBounceVertical: true,
automaticallyAdjustContentInsets: true,
automaticallyAdjustsScrollIndicatorInsets: true,
bounces: true,
bouncesZoom: true,
canCancelContentTouches: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type ScrollViewNativeProps = $ReadOnly<{
alwaysBounceHorizontal?: ?boolean,
alwaysBounceVertical?: ?boolean,
automaticallyAdjustContentInsets?: ?boolean,
automaticallyAdjustsScrollIndicatorInsets?: ?boolean,
bounces?: ?boolean,
bouncesZoom?: ?boolean,
canCancelContentTouches?: ?boolean,
Expand Down
1 change: 1 addition & 0 deletions Libraries/Components/ScrollView/ScrollViewViewConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ const ScrollViewViewConfig = {
alwaysBounceHorizontal: true,
alwaysBounceVertical: true,
automaticallyAdjustContentInsets: true,
automaticallyAdjustsScrollIndicatorInsets: true,
bounces: true,
bouncesZoom: true,
canCancelContentTouches: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ - (void)updateProps:(Props::Shared const &)props oldProps:(Props::Shared const &
scrollView.snapToOffsets = snapToOffsets;
}

if (@available(iOS 13.0, *)) {
if (oldScrollViewProps.automaticallyAdjustsScrollIndicatorInsets != newScrollViewProps.automaticallyAdjustsScrollIndicatorInsets) {
scrollView.automaticallyAdjustsScrollIndicatorInsets = newScrollViewProps.automaticallyAdjustsScrollIndicatorInsets;
}
}

if (@available(iOS 11.0, *)) {
if (oldScrollViewProps.contentInsetAdjustmentBehavior != newScrollViewProps.contentInsetAdjustmentBehavior) {
auto const contentInsetAdjustmentBehavior = newScrollViewProps.contentInsetAdjustmentBehavior;
Expand Down
12 changes: 12 additions & 0 deletions React/Views/ScrollView/RCTScrollView.m
Original file line number Diff line number Diff line change
Expand Up @@ -928,6 +928,18 @@ -(type)getter \
RCT_SET_AND_PRESERVE_OFFSET(setZoomScale, zoomScale, CGFloat);
RCT_SET_AND_PRESERVE_OFFSET(setScrollIndicatorInsets, scrollIndicatorInsets, UIEdgeInsets);

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* __IPHONE_13_0 */
- (void)setAutomaticallyAdjustsScrollIndicatorInsets:(BOOL)automaticallyAdjusts API_AVAILABLE(ios(13.0))
{
// `automaticallyAdjustsScrollIndicatorInsets` is available since iOS 13.
if ([_scrollView respondsToSelector:@selector(setAutomaticallyAdjustsScrollIndicatorInsets:)]) {
if (@available(iOS 13.0, *)) {
_scrollView.automaticallyAdjustsScrollIndicatorInsets = automaticallyAdjusts;
}
}
}
#endif

#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
- (void)setContentInsetAdjustmentBehavior:(UIScrollViewContentInsetAdjustmentBehavior)behavior API_AVAILABLE(ios(11.0))
{
Expand Down
3 changes: 3 additions & 0 deletions React/Views/ScrollView/RCTScrollViewManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ - (UIView *)view
RCT_EXPORT_VIEW_PROPERTY(onMomentumScrollBegin, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(onMomentumScrollEnd, RCTDirectEventBlock)
RCT_EXPORT_VIEW_PROPERTY(inverted, BOOL)
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 /* __IPHONE_13_0 */
RCT_EXPORT_VIEW_PROPERTY(automaticallyAdjustsScrollIndicatorInsets, BOOL)
#endif
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
RCT_EXPORT_VIEW_PROPERTY(contentInsetAdjustmentBehavior, UIScrollViewContentInsetAdjustmentBehavior)
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ ScrollViewProps::ScrollViewProps(
"automaticallyAdjustContentInsets",
sourceProps.automaticallyAdjustContentInsets,
{})),
automaticallyAdjustsScrollIndicatorInsets(convertRawProp(
rawProps,
"automaticallyAdjustsScrollIndicatorInsets",
sourceProps.automaticallyAdjustsScrollIndicatorInsets,
true)),
decelerationRate(convertRawProp(
rawProps,
"decelerationRate",
Expand Down Expand Up @@ -206,6 +211,10 @@ SharedDebugStringConvertibleList ScrollViewProps::getDebugProps() const {
"automaticallyAdjustContentInsets",
automaticallyAdjustContentInsets,
defaultScrollViewProps.automaticallyAdjustContentInsets),
debugStringConvertibleItem(
"automaticallyAdjustsScrollIndicatorInsets",
automaticallyAdjustsScrollIndicatorInsets,
defaultScrollViewProps.automaticallyAdjustsScrollIndicatorInsets),
debugStringConvertibleItem(
"decelerationRate",
decelerationRate,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class ScrollViewProps final : public ViewProps {
bool canCancelContentTouches{true};
bool centerContent{};
bool automaticallyAdjustContentInsets{};
bool automaticallyAdjustsScrollIndicatorInsets{true};
Float decelerationRate{0.998f};
bool directionalLockEnabled{};
ScrollViewIndicatorStyle indicatorStyle{};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
'use strict';

const React = require('react');

const {
Button,
Dimensions,
Modal,
ScrollView,
StyleSheet,
Switch,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no-unused-vars: 'Switch' is assigned a value but never used.

Text,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no-unused-vars: 'Text' is assigned a value but never used.

View,
} = require('react-native');

class ScrollViewIndicatorInsetsExample extends React.Component<
{...},
{|
enableAutoIndicatorInsets: boolean,
modalPresentationStyle: string,
modalVisible: boolean,
|},
> {
state = {
enableAutoIndicatorInsets: true,
modalPresentationStyle: null,
modalVisible: false,
};

_setModalVisible = (modalVisible, modalPresentationStyle) => {
this.setState({
enableAutoIndicatorInsets: true,
modalVisible,
modalPresentationStyle,
});
};

_setEnableAutoIndicatorInsets = enableAutoIndicatorInsets => {
this.setState({
enableAutoIndicatorInsets,
});
};

render() {
const {height, width} = Dimensions.get('window');
return (
<View>
<Modal
animationType="slide"
visible={this.state.modalVisible}
onRequestClose={() => this._setModalVisible(false)}
presentationStyle={this.state.modalPresentationStyle}
statusBarTranslucent={false}
supportedOrientations={['portrait', 'landscape']}>
<View style={styles.modal}>
<ScrollView
contentContainerStyle={[
styles.scrollViewContent,
{
height: (height * 1.2),
width: (width * 1.2),
},
]}
automaticallyAdjustsScrollIndicatorInsets={this.state.enableAutoIndicatorInsets}
style={styles.scrollView}>
<Text>automaticallyAdjustsScrollIndicatorInsets</Text>
<Switch
onValueChange={v => this._setEnableAutoIndicatorInsets(v)}
value={this.state.enableAutoIndicatorInsets}
style={styles.switch}/>
<Button
onPress={() => this._setModalVisible(false)}
title="Close"/>
</ScrollView>
</View>
</Modal>
<Button
onPress={() => this._setModalVisible(true, 'pageSheet')}
title="Present Sheet Modal with ScrollView"/>
<Button
onPress={() => this._setModalVisible(true, 'fullscreen')}
title="Present Fullscreen Modal with ScrollView"/>
</View>
);
}
}

const styles = StyleSheet.create({
modal: {
flex: 1,
},
scrollView: {
flex: 1,
height: 1000,
},
scrollViewContent: {
alignItems: 'center',
backgroundColor: '#ffaaaa',
justifyContent: 'flex-start',
paddingTop: 200,
},
switch: {
marginBottom: 40,
},
});

exports.title = 'ScrollViewIndicatorInsets';
exports.category = 'iOS';
exports.description =
'ScrollView automaticallyAdjustsScrollIndicatorInsets adjusts scroll indicator insets using OS-defined logic on iOS 13+.';
exports.examples = [
{
title: '<ScrollView> automaticallyAdjustsScrollIndicatorInsets Example',
render: (): React.Node => <ScrollViewIndicatorInsetsExample/>,
},
];
4 changes: 4 additions & 0 deletions packages/rn-tester/js/utils/RNTesterList.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ const ComponentExamples: Array<RNTesterExample> = [
module: require('../examples/ScrollView/ScrollViewAnimatedExample'),
supportsTVOS: true,
},
{
key: 'ScrollViewIndicatorInsetsExample',
module: require('../examples/ScrollView/ScrollViewIndicatorInsetsExample'),
},
{
key: 'SectionList-inverted',
module: require('../examples/SectionList/SectionList-inverted'),
Expand Down