-
Notifications
You must be signed in to change notification settings - Fork 24.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Summary: <SafeAreaView> renders nested content and automatically applies paddings reflect the portion of the view that is not covered by navigation bars, tab bars, toolbars, and other ancestor views. Moreover, and most importantly, Safe Area's paddings feflect physical limitation of the screen, such as rounded corners or camera notches (aka sensor housing area on iPhone X). Reviewed By: mmmulani Differential Revision: D5886411 fbshipit-source-id: 7ecc7aa34de8f5527c4e59b0fb4efba3aaea28c8
- Loading branch information
1 parent
8b4ed94
commit 983b054
Showing
11 changed files
with
307 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* @providesModule SafeAreaView | ||
* @flow | ||
*/ | ||
'use strict'; | ||
|
||
module.exports = require('View'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
* | ||
* @providesModule SafeAreaView | ||
* @flow | ||
* @format | ||
*/ | ||
|
||
const React = require('React'); | ||
const ViewPropTypes = require('ViewPropTypes'); | ||
const requireNativeComponent = require('requireNativeComponent'); | ||
|
||
import type {ViewProps} from 'ViewPropTypes'; | ||
|
||
type Props = ViewProps & { | ||
children: any, | ||
}; | ||
|
||
/** | ||
* Renders nested content and automatically applies paddings reflect the portion of the view | ||
* that is not covered by navigation bars, tab bars, toolbars, and other ancestor views. | ||
* Moreover, and most importantly, Safe Area's paddings feflect physical limitation of the screen, | ||
* such as rounded corners or camera notches (aka sensor housing area on iPhone X). | ||
*/ | ||
class SafeAreaView extends React.Component<Props> { | ||
static propTypes = { | ||
...ViewPropTypes, | ||
}; | ||
|
||
render() { | ||
return <RCTSafeAreaView {...this.props} />; | ||
} | ||
} | ||
|
||
const RCTSafeAreaView = requireNativeComponent('RCTSafeAreaView', { | ||
name: 'RCTSafeAreaView', | ||
displayName: 'RCTSafeAreaView', | ||
propTypes: { | ||
...ViewPropTypes, | ||
}, | ||
}); | ||
|
||
module.exports = SafeAreaView; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
#import <React/RCTShadowView.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface RCTSafeAreaShadowView : RCTShadowView | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
#import "RCTSafeAreaShadowView.h" | ||
|
||
#import <React/RCTAssert.h> | ||
#import <yoga/Yoga.h> | ||
|
||
#import "RCTSafeAreaViewLocalData.h" | ||
|
||
@implementation RCTSafeAreaShadowView | ||
|
||
- (void)setLocalData:(RCTSafeAreaViewLocalData *)localData | ||
{ | ||
RCTAssert([localData isKindOfClass:[RCTSafeAreaViewLocalData class]], | ||
@"Local data object for `RCTSafeAreaShadowView` must be `RCTSafeAreaViewLocalData` instance."); | ||
|
||
UIEdgeInsets insets = localData.insets; | ||
|
||
super.paddingLeft = (YGValue){insets.left, YGUnitPoint}; | ||
super.paddingRight = (YGValue){insets.right, YGUnitPoint}; | ||
super.paddingTop = (YGValue){insets.top, YGUnitPoint}; | ||
super.paddingBottom = (YGValue){insets.bottom, YGUnitPoint}; | ||
|
||
[self didSetProps:@[@"paddingLeft", @"paddingRight", @"paddingTop", @"paddingBottom"]]; | ||
} | ||
|
||
/** | ||
* Removing support for setting padding from any outside code | ||
* to prevent interferring this with local data. | ||
*/ | ||
- (void)setPadding:(YGValue)value {} | ||
- (void)setPaddingLeft:(YGValue)value {} | ||
- (void)setPaddingRight:(YGValue)value {} | ||
- (void)setPaddingTop:(YGValue)value {} | ||
- (void)setPaddingBottom:(YGValue)value {} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
#import <React/RCTView.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@class RCTBridge; | ||
|
||
@interface RCTSafeAreaView : RCTView | ||
|
||
- (instancetype)initWithBridge:(RCTBridge *)bridge; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
#import "RCTSafeAreaView.h" | ||
|
||
#import <React/RCTBridge.h> | ||
#import <React/RCTUIManager.h> | ||
|
||
#import "RCTSafeAreaViewLocalData.h" | ||
|
||
@implementation RCTSafeAreaView { | ||
RCTBridge *_bridge; | ||
UIEdgeInsets _currentSafeAreaInsets; | ||
} | ||
|
||
- (instancetype)initWithBridge:(RCTBridge *)bridge | ||
{ | ||
if (self = [super initWithFrame:CGRectZero]) { | ||
_bridge = bridge; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
RCT_NOT_IMPLEMENTED(- (instancetype)initWithCoder:(NSCoder *)decoder) | ||
RCT_NOT_IMPLEMENTED(- (instancetype)initWithFrame:(CGRect)frame) | ||
|
||
#if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 /* __IPHONE_11_0 */ | ||
|
||
static BOOL UIEdgeInsetsEqualToEdgeInsetsWithThreshold(UIEdgeInsets insets1, UIEdgeInsets insets2, CGFloat threshold) { | ||
return | ||
ABS(insets1.left - insets2.left) <= threshold && | ||
ABS(insets1.right - insets2.right) <= threshold && | ||
ABS(insets1.top - insets2.top) <= threshold && | ||
ABS(insets1.bottom - insets2.bottom) <= threshold; | ||
} | ||
|
||
- (void)safeAreaInsetsDidChange | ||
{ | ||
if (![self respondsToSelector:@selector(safeAreaInsets)]) { | ||
return; | ||
} | ||
|
||
UIEdgeInsets safeAreaInsets = self.safeAreaInsets; | ||
|
||
if (UIEdgeInsetsEqualToEdgeInsetsWithThreshold(safeAreaInsets, _currentSafeAreaInsets, 1.0 / RCTScreenScale())) { | ||
return; | ||
} | ||
|
||
_currentSafeAreaInsets = safeAreaInsets; | ||
|
||
RCTSafeAreaViewLocalData *localData = | ||
[[RCTSafeAreaViewLocalData alloc] initWithInsets:safeAreaInsets]; | ||
[_bridge.uiManager setLocalData:localData forView:self]; | ||
} | ||
|
||
#endif | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
#import <UIKit/UIKit.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface RCTSafeAreaViewLocalData : NSObject | ||
|
||
- (instancetype)initWithInsets:(UIEdgeInsets)insets; | ||
|
||
@property (atomic, readonly) UIEdgeInsets insets; | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
#import "RCTSafeAreaViewLocalData.h" | ||
|
||
@implementation RCTSafeAreaViewLocalData | ||
|
||
- (instancetype)initWithInsets:(UIEdgeInsets)insets | ||
{ | ||
if (self = [super init]) { | ||
_insets = insets; | ||
} | ||
|
||
return self; | ||
} | ||
|
||
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
#import <React/RCTViewManager.h> | ||
|
||
NS_ASSUME_NONNULL_BEGIN | ||
|
||
@interface RCTSafeAreaViewManager : RCTViewManager | ||
|
||
@end | ||
|
||
NS_ASSUME_NONNULL_END |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
/** | ||
* Copyright (c) 2015-present, Facebook, Inc. | ||
* All rights reserved. | ||
* | ||
* This source code is licensed under the BSD-style license found in the | ||
* LICENSE file in the root directory of this source tree. An additional grant | ||
* of patent rights can be found in the PATENTS file in the same directory. | ||
*/ | ||
|
||
#import "RCTSafeAreaViewManager.h" | ||
|
||
#import "RCTSafeAreaShadowView.h" | ||
#import "RCTSafeAreaView.h" | ||
#import "RCTUIManager.h" | ||
|
||
@implementation RCTSafeAreaViewManager | ||
|
||
RCT_EXPORT_MODULE() | ||
|
||
- (UIView *)view | ||
{ | ||
return [[RCTSafeAreaView alloc] initWithBridge:self.bridge]; | ||
} | ||
|
||
- (RCTSafeAreaShadowView *)shadowView | ||
{ | ||
return [RCTSafeAreaShadowView new]; | ||
} | ||
|
||
@end |
983b054
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shergin Do you know how to make SafeArea different colours?
For example orange on the top and grey on the bottom
I believe facebook app is also solving it somehow.
Maybe if replace here https://github.com/facebook/react-native/blob/master/React/Views/SafeAreaView/RCTSafeAreaShadowView.m#L26
paddings with borders then would be possible to set colour for each side.
983b054
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@skv-headless Just wrap with another with background color.
983b054
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shergin What is I need two different colors on same page? One for top and one for bottom.
983b054
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Nodonisko Well, SafeAreaView is about insets, not about colors. You can solve your problem customizing the background view's background (something like applying 50/50 top/bottom splitted color).
But.. yeah, I have to admit, there is no way to dedicated special view to top or bottom inset area, but it is very interesting idea, I will think about that.
983b054
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have wrote a demo as @shergin said, post here if anyone needed.
983b054
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shergin @wd Thanks!
983b054
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@shergin:
Could you consider props for splitting these between two different locales? Something like
forceInset
inreact-community/react-native-safe-area-view
?e.g. SafeAreaView with support for defining which edges to make "safe"? This way
SafeAreaView
could have independent use on root/container/component levels depending on need, while maintaining the ability to support different backgrounds on each.