Resolve relative size rendering error in inspector (#23804)

Summary:
Currently, when relative sizes are given in margin or padding stylings (be it a percentage or an auto measure), the inspector crashes, due to frame rendering not properly handling those kinds of measurements. This PR adds a resolution step for them:

* Percentages are evaluated relative to the window size.
* I decided to simply not render `auto` margins/paddings, due to the complexities involved (e.g. when the margin is between multiple elements with relative sizes).

Since the inspector does not crash anymore on relative sizes on paddings or margins, I believe that this addresses #17496.

Fixes #17496

[General] [Fixed] - Fix inspector rendering of relative margins and paddings
Pull Request resolved: https://github.com/facebook/react-native/pull/23804

Differential Revision: D14437273

Pulled By: cpojer

fbshipit-source-id: c9f0f71a2e1b2399a2b2148cef2124787703ead3
This commit is contained in:
Georgios Andreadis
2019-03-13 02:00:55 -07:00
committed by Facebook Github Bot
parent fc3225d0f1
commit 972ee2edbd

View File

@@ -14,6 +14,7 @@ const BorderBox = require('BorderBox');
const React = require('React');
const StyleSheet = require('StyleSheet');
const View = require('View');
const Dimensions = require('Dimensions');
const flattenStyle = require('flattenStyle');
const resolveBoxStyle = require('resolveBoxStyle');
@@ -21,8 +22,8 @@ const resolveBoxStyle = require('resolveBoxStyle');
class ElementBox extends React.Component<$FlowFixMeProps> {
render() {
const style = flattenStyle(this.props.style) || {};
const margin = resolveBoxStyle('margin', style);
const padding = resolveBoxStyle('padding', style);
let margin = resolveBoxStyle('margin', style);
let padding = resolveBoxStyle('padding', style);
const frameStyle = {...this.props.frame};
const contentStyle = {
@@ -31,6 +32,8 @@ class ElementBox extends React.Component<$FlowFixMeProps> {
};
if (margin != null) {
margin = resolveRelativeSizes(margin);
frameStyle.top -= margin.top;
frameStyle.left -= margin.left;
frameStyle.height += margin.top + margin.bottom;
@@ -51,6 +54,8 @@ class ElementBox extends React.Component<$FlowFixMeProps> {
}
if (padding != null) {
padding = resolveRelativeSizes(padding);
contentStyle.width -= padding.left + padding.right;
contentStyle.height -= padding.top + padding.bottom;
}
@@ -82,4 +87,51 @@ const styles = StyleSheet.create({
},
});
type Style = {
top: number,
right: number,
bottom: number,
left: number,
};
/**
* Resolves relative sizes (percentages and auto) in a style object.
*
* @param style the style to resolve
* @return a modified copy
*/
function resolveRelativeSizes(style: $ReadOnly<Style>): Style {
let resolvedStyle = Object.assign({}, style);
resolveSizeInPlace(resolvedStyle, 'top', 'height');
resolveSizeInPlace(resolvedStyle, 'right', 'width');
resolveSizeInPlace(resolvedStyle, 'bottom', 'height');
resolveSizeInPlace(resolvedStyle, 'left', 'width');
return resolvedStyle;
}
/**
* Resolves the given size of a style object in place.
*
* @param style the style object to modify
* @param direction the direction to resolve (e.g. 'top')
* @param dimension the window dimension that this direction belongs to (e.g. 'height')
*/
function resolveSizeInPlace(
style: Style,
direction: string,
dimension: string,
) {
if (style[direction] !== null && typeof style[direction] === 'string') {
if (style[direction].indexOf('%') !== -1) {
style[direction] =
(parseFloat(style[direction]) / 100.0) *
Dimensions.get('window')[dimension];
}
if (style[direction] === 'auto') {
// Ignore auto sizing in frame drawing due to complexity of correctly rendering this
style[direction] = 0;
}
}
}
module.exports = ElementBox;