Add 'contentInsetAdjustmentBehavior' (new in iOS 11) to ScrollView
Summary: In iOS11, Apple added a new layout feature called "Safe Areas" (this blog post talks a bit about it: https://www.bignerdranch.com/blog/wwdc-2017-large-titles-and-safe-area-layout-guides/). UIScrollView is one component that is affected by this change in Apple's API. When the `contentInsetAdjustmentBehavior` is set to `automatic`, for example, it will adjust the insets (and override any manually set insets) automatically based on whether or not there's a UINavigationBar, a UITabBar, a visible status bar, etc on the screen. Frustratingly, Apple decided to default to `Automatic` for this behavior, which will cause any apps that set contentInset/contentContainerStyle padding to have their values offset by, at the very least, the size of the status bar, when they compile their app for iOS 11. Here's more information about this behavior: https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior?language=objc Mostly, this is a really straightforward change -- it simply adds a new iOS-only prop to ScrollView that allows setting `contentInsetAdjustmentBehavior`. But I did decide to default the behavior to `never`, so that it mimics the behavior we've seen in iOS < 11. I think it's good to keep something as crucial as scrollview content insets non-magical, and also keep it behaving similarly between platforms. Closes https://github.com/facebook/react-native/pull/15023 Reviewed By: javache Differential Revision: D5517552 Pulled By: hramos fbshipit-source-id: c9ce4bf331b3d243228268d826fdd4dcee99981d
This commit is contained in:
parent
73f8352e92
commit
1954438533
|
@ -360,7 +360,18 @@ const ScrollView = createReactClass({
|
|||
* @platform ios
|
||||
*/
|
||||
zoomScale: PropTypes.number,
|
||||
|
||||
/**
|
||||
* This property specifies how the safe area insets are used to modify the
|
||||
* content area of the scroll view. The default value of this property is
|
||||
* "never". Available on iOS 11 and later.
|
||||
* @platform ios
|
||||
*/
|
||||
contentInsetAdjustmentBehavior: PropTypes.oneOf([
|
||||
'automatic',
|
||||
'scrollableAxes',
|
||||
'never', // default
|
||||
'always',
|
||||
]),
|
||||
/**
|
||||
* A RefreshControl component, used to provide pull-to-refresh
|
||||
* functionality for the ScrollView. Only works for vertical ScrollViews
|
||||
|
|
|
@ -354,10 +354,22 @@ RCT_NOT_IMPLEMENTED(- (instancetype)init)
|
|||
|
||||
if ((self = [super initWithFrame:CGRectZero])) {
|
||||
_eventDispatcher = eventDispatcher;
|
||||
|
||||
_scrollView = [[RCTCustomScrollView alloc] initWithFrame:CGRectZero];
|
||||
_scrollView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
|
||||
_scrollView.delegate = self;
|
||||
_scrollView.delaysContentTouches = NO;
|
||||
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
|
||||
// `contentInsetAdjustmentBehavior` is only available since iOS 11.
|
||||
// We set the default behavior to "never" so that iOS
|
||||
// doesn't do weird things to UIScrollView insets automatically
|
||||
// and keeps it as an opt-in behavior.
|
||||
if ([_scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
|
||||
_scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
|
||||
}
|
||||
#endif
|
||||
|
||||
_automaticallyAdjustContentInsets = YES;
|
||||
_DEPRECATED_sendUpdatedChildFrames = NO;
|
||||
_contentInset = UIEdgeInsetsZero;
|
||||
|
@ -901,6 +913,18 @@ RCT_SET_AND_PRESERVE_OFFSET(setShowsVerticalScrollIndicator, showsVerticalScroll
|
|||
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 >= 110000 /* __IPHONE_11_0 */
|
||||
- (void)setContentInsetAdjustmentBehavior:(UIScrollViewContentInsetAdjustmentBehavior)behavior
|
||||
{
|
||||
// `contentInsetAdjustmentBehavior` is available since iOS 11.
|
||||
if ([_scrollView respondsToSelector:@selector(setContentInsetAdjustmentBehavior:)]) {
|
||||
CGPoint contentOffset = _scrollView.contentOffset;
|
||||
_scrollView.contentInsetAdjustmentBehavior = behavior;
|
||||
_scrollView.contentOffset = contentOffset;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
- (void)sendScrollEventWithName:(NSString *)eventName
|
||||
scrollView:(UIScrollView *)scrollView
|
||||
userData:(NSDictionary *)userData
|
||||
|
|
|
@ -36,6 +36,15 @@ RCT_ENUM_CONVERTER(UIScrollViewIndicatorStyle, (@{
|
|||
@"white": @(UIScrollViewIndicatorStyleWhite),
|
||||
}), UIScrollViewIndicatorStyleDefault, integerValue)
|
||||
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
|
||||
RCT_ENUM_CONVERTER(UIScrollViewContentInsetAdjustmentBehavior, (@{
|
||||
@"automatic": @(UIScrollViewContentInsetAdjustmentAutomatic),
|
||||
@"scrollableAxes": @(UIScrollViewContentInsetAdjustmentScrollableAxes),
|
||||
@"never": @(UIScrollViewContentInsetAdjustmentNever),
|
||||
@"always": @(UIScrollViewContentInsetAdjustmentAlways),
|
||||
}), UIScrollViewContentInsetAdjustmentNever, integerValue)
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
@implementation RCTScrollViewManager
|
||||
|
@ -80,6 +89,9 @@ RCT_EXPORT_VIEW_PROPERTY(onScrollEndDrag, RCTDirectEventBlock)
|
|||
RCT_EXPORT_VIEW_PROPERTY(onMomentumScrollBegin, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(onMomentumScrollEnd, RCTDirectEventBlock)
|
||||
RCT_EXPORT_VIEW_PROPERTY(DEPRECATED_sendUpdatedChildFrames, BOOL)
|
||||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */
|
||||
RCT_EXPORT_VIEW_PROPERTY(contentInsetAdjustmentBehavior, UIScrollViewContentInsetAdjustmentBehavior)
|
||||
#endif
|
||||
|
||||
// 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
|
||||
|
|
Loading…
Reference in New Issue