@@ -6,11 +6,11 @@ import {
66 NativeModules ,
77 Platform ,
88 SafeAreaView ,
9+ StyleSheet ,
910 View ,
1011} from 'react-native' ;
1112import withOrientation from './withOrientation' ;
1213
13- const { isIPhoneX_deprecated } = DeviceInfo ;
1414// See https://mydevice.io/devices/ for device dimensions
1515const X_WIDTH = 375 ;
1616const X_HEIGHT = 812 ;
@@ -23,8 +23,10 @@ const { PlatformConstants = {} } = NativeModules;
2323const { minor = 0 } = PlatformConstants . reactNativeVersion || { } ;
2424
2525const isIPhoneX = ( ( ) => {
26+ if ( Platform . OS === 'web' ) return false ;
27+
2628 if ( minor >= 50 ) {
27- return isIPhoneX_deprecated ;
29+ return DeviceInfo . isIPhoneX_deprecated ;
2830 }
2931
3032 return (
@@ -62,13 +64,27 @@ const statusBarHeight = isLandscape => {
6264 return isLandscape ? 0 : 20 ;
6365} ;
6466
67+ const doubleFromPercentString = percent => {
68+ if ( ! percent . includes ( '%' ) ) {
69+ return 0 ;
70+ }
71+
72+ const dbl = parseFloat ( percent ) / 100 ;
73+
74+ if ( isNaN ( dbl ) ) return 0 ;
75+
76+ return dbl ;
77+ } ;
78+
6579class SafeView extends Component {
6680 state = {
6781 touchesTop : true ,
6882 touchesBottom : true ,
6983 touchesLeft : true ,
7084 touchesRight : true ,
7185 orientation : null ,
86+ viewWidth : 0 ,
87+ viewHeight : 0 ,
7288 } ;
7389
7490 componentDidMount ( ) {
@@ -88,17 +104,13 @@ class SafeView extends Component {
88104 return < View style = { style } > { this . props . children } </ View > ;
89105 }
90106
91- if ( ! forceInset && minor >= 50 ) {
92- return < SafeAreaView style = { style } > { this . props . children } </ SafeAreaView > ;
93- }
94-
95107 const safeAreaStyle = this . _getSafeAreaStyle ( ) ;
96108
97109 return (
98110 < View
99111 ref = { c => ( this . view = c ) }
100112 onLayout = { this . _onLayout }
101- style = { [ style , safeAreaStyle ] }
113+ style = { safeAreaStyle }
102114 >
103115 { this . props . children }
104116 </ View >
@@ -145,6 +157,8 @@ class SafeView extends Component {
145157 touchesLeft,
146158 touchesRight,
147159 orientation : newOrientation ,
160+ viewWidth : winWidth ,
161+ viewHeight : winHeight ,
148162 } ) ;
149163 } ) ;
150164 } ;
@@ -153,7 +167,16 @@ class SafeView extends Component {
153167 const { touchesTop, touchesBottom, touchesLeft, touchesRight } = this . state ;
154168 const { forceInset, isLandscape } = this . props ;
155169
170+ const {
171+ paddingTop,
172+ paddingBottom,
173+ paddingLeft,
174+ paddingRight,
175+ viewStyle,
176+ } = this . _getViewStyles ( ) ;
177+
156178 const style = {
179+ ...viewStyle ,
157180 paddingTop : touchesTop ? this . _getInset ( 'top' ) : 0 ,
158181 paddingBottom : touchesBottom ? this . _getInset ( 'bottom' ) : 0 ,
159182 paddingLeft : touchesLeft ? this . _getInset ( 'left' ) : 0 ,
@@ -195,9 +218,64 @@ class SafeView extends Component {
195218 } ) ;
196219 }
197220
221+ // new height/width should only include padding from insets
222+ // height/width should not be affected by padding from style obj
223+ if ( style . height && typeof style . height === 'number' ) {
224+ style . height += style . paddingTop + style . paddingBottom ;
225+ }
226+
227+ if ( style . width && typeof style . width === 'number' ) {
228+ style . width += style . paddingLeft + style . paddingRight ;
229+ }
230+
231+ style . paddingTop += paddingTop ;
232+ style . paddingBottom += paddingBottom ;
233+ style . paddingLeft += paddingLeft ;
234+ style . paddingRight += paddingRight ;
235+
198236 return style ;
199237 } ;
200238
239+ _getViewStyles = ( ) => {
240+ const { viewWidth } = this . state ;
241+ // get padding values from style to add back in after insets are determined
242+ // default precedence: padding[Side] -> vertical | horizontal -> padding -> 0
243+ let {
244+ padding = 0 ,
245+ paddingVertical = padding ,
246+ paddingHorizontal = padding ,
247+ paddingTop = paddingVertical ,
248+ paddingBottom = paddingVertical ,
249+ paddingLeft = paddingHorizontal ,
250+ paddingRight = paddingHorizontal ,
251+ ...viewStyle
252+ } = StyleSheet . flatten ( this . props . style || { } ) ;
253+
254+ if ( typeof paddingTop !== 'number' ) {
255+ paddingTop = doubleFromPercentString ( paddingTop ) * viewWidth ;
256+ }
257+
258+ if ( typeof paddingBottom !== 'number' ) {
259+ paddingBottom = doubleFromPercentString ( paddingBottom ) * viewWidth ;
260+ }
261+
262+ if ( typeof paddingLeft !== 'number' ) {
263+ paddingLeft = doubleFromPercentString ( paddingLeft ) * viewWidth ;
264+ }
265+
266+ if ( typeof paddingRight !== 'number' ) {
267+ paddingRight = doubleFromPercentString ( paddingRight ) * viewWidth ;
268+ }
269+
270+ return {
271+ paddingTop,
272+ paddingBottom,
273+ paddingLeft,
274+ paddingRight,
275+ viewStyle,
276+ } ;
277+ } ;
278+
201279 _getInset = key => {
202280 const { isLandscape } = this . props ;
203281 switch ( key ) {
0 commit comments