mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-05 09:29:07 +08:00
BREAKING - Fix unconstraint sizing in main axis
Summary: This fixes measuring of items in the main axis of a container. Previously items were in a lot of cases measured with UNSPECIFIED instead of AT_MOST. This was to support scrolling containers. The correct way to handle scrolling containers is to instead provide them with their own overflow value to activate this behavior. This is also similar to how the web works. This is a breaking change. Most of your layouts will continue to function as before however some of them might not. Typically this is due to having a `flex: 1` style where it is currently a no-op due to being measured with an undefined size but after this change it may collapse your component to take zero size due to the implicit `flexBasis: 0` now being correctly treated. Removing the bad `flex: 1` style or changing it to `flexGrow: 1` should solve most if not all layout issues your see after this diff. Reviewed By: majak Differential Revision: D3876927 fbshipit-source-id: 81ea1c9d6574dd4564a3333f1b3617cf84b4022f
This commit is contained in:
committed by
Facebook Github Bot 6
parent
295ee16430
commit
0a9b6bedb3
@@ -51,7 +51,7 @@ public class CSSLayout {
|
||||
Arrays.fill(dimensions, CSSConstants.UNDEFINED);
|
||||
direction = CSSDirection.LTR;
|
||||
|
||||
computedFlexBasis = 0;
|
||||
computedFlexBasis = CSSConstants.UNDEFINED;
|
||||
|
||||
generationCount = 0;
|
||||
lastParentDirection = null;
|
||||
|
||||
@@ -181,6 +181,7 @@ public class CSSNode implements CSSNodeAPI<CSSNode> {
|
||||
}
|
||||
|
||||
mLayoutState = LayoutState.DIRTY;
|
||||
layout.computedFlexBasis = CSSConstants.UNDEFINED;
|
||||
|
||||
if (mParent != null) {
|
||||
mParent.dirty();
|
||||
|
||||
@@ -12,4 +12,5 @@ package com.facebook.csslayout;
|
||||
public enum CSSOverflow {
|
||||
VISIBLE,
|
||||
HIDDEN,
|
||||
SCROLL,
|
||||
}
|
||||
|
||||
@@ -695,9 +695,9 @@ public class LayoutEngine {
|
||||
// The height is definite, so use that as the flex basis.
|
||||
child.layout.computedFlexBasis = Math.max(child.style.dimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]))));
|
||||
} else if (!isFlexBasisAuto(child) && !Float.isNaN(availableInnerMainDim)) {
|
||||
|
||||
// If the basis isn't 'auto', it is assumed to be zero.
|
||||
child.layout.computedFlexBasis = Math.max(child.style.flexBasis, ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
|
||||
if (Float.isNaN(child.layout.computedFlexBasis)) {
|
||||
child.layout.computedFlexBasis = Math.max(child.style.flexBasis, ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
|
||||
}
|
||||
} else {
|
||||
|
||||
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
|
||||
@@ -715,19 +715,17 @@ public class LayoutEngine {
|
||||
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
|
||||
}
|
||||
|
||||
// According to the spec, if the main size is not definite and the
|
||||
// child's inline axis is parallel to the main axis (i.e. it's
|
||||
// horizontal), the child should be sized using "UNDEFINED" in
|
||||
// the main size. Otherwise use "AT_MOST" in the cross axis.
|
||||
if (!isMainAxisRow && Float.isNaN(childWidth) && !Float.isNaN(availableInnerWidth)) {
|
||||
childWidth = availableInnerWidth;
|
||||
childWidthMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
|
||||
// The W3C spec doesn't say anything about the 'overflow' property,
|
||||
// but all major browsers appear to implement the following logic.
|
||||
if (node.style.overflow == CSSOverflow.HIDDEN) {
|
||||
if (isMainAxisRow && Float.isNaN(childHeight) && !Float.isNaN(availableInnerHeight)) {
|
||||
if ((!isMainAxisRow && node.style.overflow == CSSOverflow.SCROLL) || node.style.overflow != CSSOverflow.SCROLL) {
|
||||
if (Float.isNaN(childWidth) && !Float.isNaN(availableInnerWidth)) {
|
||||
childWidth = availableInnerWidth;
|
||||
childWidthMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
}
|
||||
|
||||
if ((isMainAxisRow && node.style.overflow == CSSOverflow.SCROLL) || node.style.overflow != CSSOverflow.SCROLL) {
|
||||
if (Float.isNaN(childHeight) && !Float.isNaN(availableInnerHeight)) {
|
||||
childHeight = availableInnerHeight;
|
||||
childHeightMeasureMode = CSSMeasureMode.AT_MOST;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import com.facebook.csslayout.CSSAlign;
|
||||
import com.facebook.csslayout.CSSConstants;
|
||||
import com.facebook.csslayout.CSSFlexDirection;
|
||||
import com.facebook.csslayout.CSSJustify;
|
||||
import com.facebook.csslayout.CSSOverflow;
|
||||
import com.facebook.csslayout.CSSPositionType;
|
||||
import com.facebook.csslayout.CSSWrap;
|
||||
import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
@@ -102,6 +103,12 @@ public class LayoutShadowNode extends ReactShadowNode {
|
||||
justifyContent.toUpperCase(Locale.US).replace("-", "_")));
|
||||
}
|
||||
|
||||
@ReactProp(name = ViewProps.OVERFLOW)
|
||||
public void setOverflow(@Nullable String overflow) {
|
||||
setOverflow(overflow == null ? CSSOverflow.VISIBLE : CSSOverflow.valueOf(
|
||||
overflow.toUpperCase(Locale.US).replace("-", "_")));
|
||||
}
|
||||
|
||||
@ReactPropGroup(names = {
|
||||
ViewProps.MARGIN,
|
||||
ViewProps.MARGIN_VERTICAL,
|
||||
|
||||
@@ -26,6 +26,7 @@ public class ViewProps {
|
||||
// !!! Keep in sync with LAYOUT_ONLY_PROPS below
|
||||
public static final String ALIGN_ITEMS = "alignItems";
|
||||
public static final String ALIGN_SELF = "alignSelf";
|
||||
public static final String OVERFLOW = "overflow";
|
||||
public static final String BOTTOM = "bottom";
|
||||
public static final String COLLAPSABLE = "collapsable";
|
||||
public static final String FLEX = "flex";
|
||||
@@ -113,6 +114,7 @@ public class ViewProps {
|
||||
FLEX_DIRECTION,
|
||||
FLEX_WRAP,
|
||||
JUSTIFY_CONTENT,
|
||||
OVERFLOW,
|
||||
|
||||
/* position */
|
||||
POSITION,
|
||||
|
||||
Reference in New Issue
Block a user