Merge pull request #2947 from NativeScript/flexbox-ui-tests

Flexbox ui tests
This commit is contained in:
Panayot Cankov
2016-10-24 15:04:52 +03:00
committed by GitHub
7 changed files with 229 additions and 287 deletions

View File

@ -1,11 +1,3 @@
@keyframes select {
0%, 100% {
transform: scale(1, 1);
}
50% {
transform: scale(1.4, 1.4);
}
}
#container>Label { #container>Label {
border-width: 1; border-width: 1;
border-color: black; border-color: black;
@ -13,16 +5,18 @@
} }
#container>Label[selected="yes"] { #container>Label[selected="yes"] {
border-color: yellow; border-color: yellow;
/* animation-name: select;
animation-duration: 0.2s;
animation-fill-mode: forwards;
animation-iteration-count: 1;*/
} }
.control { .control {
font-size: 11; font-size: 11;
} }
.control Button { .control FlexboxLayout {
padding: 2; border-width: 0 0 1 1;
margin: 2; border-color: gray;
}
.control Button {
border-width: 1 1 0 0;
border-color: gray;
padding: 0;
height: 0;
} }

View File

@ -1,5 +1,4 @@
import {isAndroid} from "platform"; import {FlexboxLayout} from "ui/layouts/flexbox-layout";
import * as flexbox from "ui/layouts/flexbox-layout";
function set(what: string) { function set(what: string) {
return function(args) { return function(args) {
@ -15,41 +14,26 @@ export const alignContent = set("alignContent");
let lastSelection = null; let lastSelection = null;
export function select(args) { export function select(args) {
console.log("Select: " + args.object); if (lastSelection) {
lastSelection.selected = "no";
lastSelection.notify({ eventName: "selectedChange", object: lastSelection });
}
lastSelection = args.object; lastSelection = args.object;
if (lastSelection) {
if (isAndroid) { lastSelection.selected = "yes";
let layoutParams = lastSelection.android.getLayoutParams(); lastSelection.notify({ eventName: "selectedChange", object: lastSelection });
console.log("Selection: " + lastSelection + ": " + layoutParams);
console.log(" - margin: " + layoutParams.topMargin + " " + layoutParams.rightMargin + " " + layoutParams.bottomMargin + " " + layoutParams.leftMargin);
} }
} }
export function order({object}) { let whenSelected = handler => args => lastSelection && handler(args);
if (!lastSelection) { let setProperty = setter => value => setter(lastSelection, value);
return; let intHandler = handler => ({object}) => handler(parseInt(object.text));
} let stringHandler = handler => ({object}) => handler(object.text);
let value = object.text; let booleanHandler = handler => ({object}) => handler(object.text === "true");
console.log("Set order " + value + " " + lastSelection);
flexbox.FlexboxLayout.setOrder(lastSelection, object.text);
}
export function flexGrow({object}) { export const order = whenSelected(intHandler(setProperty(FlexboxLayout.setOrder)));
if (!lastSelection) { export const flexGrow = whenSelected(intHandler(setProperty(FlexboxLayout.setFlexGrow)));
return; export const flexShrink = whenSelected(intHandler(setProperty(FlexboxLayout.setFlexShrink)));
} export const alignSelf = whenSelected(stringHandler(setProperty(FlexboxLayout.setAlignSelf)));
let value = object.text; export const flexWrapBefore = whenSelected(booleanHandler(setProperty(FlexboxLayout.setFlexWrapBefore)));
console.log("Set flexGrow " + value + " " + lastSelection);
flexbox.FlexboxLayout.setFlexGrow(lastSelection, object.text);
}
export function flexShrink({object}) {
if (!lastSelection) {
return;
}
let value = object.text;
console.log("Set flexShrink " + value + " " + lastSelection);
flexbox.FlexboxLayout.setFlexShrink(lastSelection, object.text);
}
// TODO: Align self

View File

@ -1,119 +1,109 @@
<Page xmlns="http://schemas.nativescript.org/tns.xsd"> <Page xmlns="http://schemas.nativescript.org/tns.xsd">
<GridLayout rows="auto, *" backgroundColor="gray"> <GridLayout rows="auto, *">
<GridLayout class="control" columns="auto, *" rows="30, 30, 30, 30, 30, 25, 30, 30, 30, 30"> <GridLayout class="control" columns="auto, *" rows="30, 30, 30, 30, 30, 25, 15, 15, 15, 30, 30">
<Label row="0" text="FlexDirection" verticalAlignment="center" /> <Label row="0" text="FlexDirection" verticalAlignment="center" />
<StackLayout row="0" col="1" orientation="horizontal"> <FlexboxLayout row="0" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="row" tap="flexDirection" /> <Button text="row" tap="flexDirection" flexGrow="1" automationText="flexDirection-row" />
<Button text="row-reverse" tap="flexDirection" /> <Button text="row-reverse" tap="flexDirection" flexGrow="1" automationText="flexDirection-row-reverse" />
<Button text="column" tap="flexDirection" /> <Button text="column" tap="flexDirection" flexGrow="1" automationText="flexDirection-column" />
<Button text="column-reverse" tap="flexDirection" /> <Button text="column-reverse" tap="flexDirection" flexGrow="1" automationText="flexDirection-column-reverse" />
</StackLayout> </FlexboxLayout>
<Label row="1" text="FlexWrap" verticalAlignment="center" /> <Label row="1" text="FlexWrap" verticalAlignment="center" />
<StackLayout row="1" col="1" orientation="horizontal"> <FlexboxLayout row="1" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="nowrap" tap="flexWrap" /> <Button text="nowrap" tap="flexWrap" flexGrow="1" automationText="flexWrap-nowrap" />
<Button text="wrap" tap="flexWrap" /> <Button text="wrap" tap="flexWrap" flexGrow="1" automationText="flexWrap-wrap" />
<Button text="wrap-reverse" tap="flexWrap" /> <Button text="wrap-reverse" tap="flexWrap" flexGrow="1" automationText="flexWrap-wrap-reverse" />
</StackLayout> </FlexboxLayout>
<!-- TODO: Stretch seems to be default in JavaScript, but not default in Java -->
<Label row="2" text="JustifyContent" verticalAlignment="center" /> <Label row="2" text="JustifyContent" verticalAlignment="center" />
<StackLayout row="2" col="1" orientation="horizontal"> <FlexboxLayout row="2" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="flex-start" tap="justifyContent" /> <Button text="flex-start" tap="justifyContent" flexGrow="1" automationText="justifyContent-flex-start" />
<Button text="flex-end" tap="justifyContent" /> <Button text="flex-end" tap="justifyContent" flexGrow="1" automationText="justifyContent-flex-end" />
<Button text="center" tap="justifyContent" /> <Button text="center" tap="justifyContent" flexGrow="1" automationText="justifyContent-center" />
<Button text="space-between" tap="justifyContent" /> <Button text="space-between" tap="justifyContent" flexGrow="1" automationText="justifyContent-space-between" />
<Button text="space-around" tap="justifyContent" /> <Button text="space-around" tap="justifyContent" flexGrow="1" automationText="justifyContent-space-around" />
</StackLayout> </FlexboxLayout>
<Label row="3" text="AlignItems" verticalAlignment="center" /> <Label row="3" text="alignItems" verticalAlignment="center" />
<StackLayout row="3" col="1" orientation="horizontal"> <FlexboxLayout row="3" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="flex-start" tap="alignItems" /> <Button text="flex-start" tap="alignItems" flexGrow="1" automationText="alignItems-flex-start" />
<Button text="flex-end" tap="alignItems" /> <Button text="flex-end" tap="alignItems" flexGrow="1" automationText="alignItems-flex-end" />
<Button text="center" tap="alignItems" /> <Button text="center" tap="alignItems" flexGrow="1" automationText="alignItems-center" />
<Button text="baseline" tap="alignItems" /> <Button text="baseline" tap="alignItems" flexGrow="1" automationText="alignItems-baseline" />
<Button text="stretch" tap="alignItems" /> <Button text="stretch" tap="alignItems" flexGrow="1" automationText="alignItems-stretch" />
</StackLayout> </FlexboxLayout>
<Label row="4" text="AlignContent" verticalAlignment="center" /> <Label row="4" text="alignContent" verticalAlignment="center" />
<StackLayout row="4" col="1" orientation="horizontal"> <FlexboxLayout row="4" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="flex-start" tap="alignContent" /> <Button text="flex-start" tap="alignContent" flexGrow="1" automationText="alignItems-flex-start" />
<Button text="flex-end" tap="alignContent" /> <Button text="flex-end" tap="alignContent" flexGrow="1" automationText="alignItems-flex-end" />
<Button text="center" tap="alignContent" /> <Button text="center" tap="alignContent" flexGrow="1" automationText="alignItems-center" />
<Button text="space-between" tap="alignContent" /> <Button text="space-between" tap="alignContent" flexGrow="1" automationText="alignItems-space-between" />
<Button text="space-around" tap="alignContent" /> <Button text="space-around" tap="alignContent" flexGrow="1" automationText="alignItems-space-around" />
<Button text="stretch" tap="alignContent" /> <Button text="stretch" tap="alignContent" flexGrow="1" automationText="alignItems-stretch" />
</StackLayout> </FlexboxLayout>
<Label row="5" colSpan="2" text="--- selected item properties ---" /> <Label row="5" colSpan="2" text="--- selected item properties ---" />
<Label text="order" row="6" /> <Label text="order" row="6" />
<StackLayout row="6" col="1" orientation="horizontal"> <FlexboxLayout row="6" col="1" alignContent="stretch">
<Button text="0" tap="order" /> <Button text="0" tap="order" flexGrow="1" automationText="order-0" />
<Button text="1" tap="order" /> <Button text="1" tap="order" flexGrow="1" automationText="order-1" />
<Button text="2" tap="order" /> <Button text="2" tap="order" flexGrow="1" automationText="order-2" />
<Button text="3" tap="order" /> <Button text="3" tap="order" flexGrow="1" automationText="order-3" />
<Button text="4" tap="order" /> <Button text="4" tap="order" flexGrow="1" automationText="order-4" />
</StackLayout> </FlexboxLayout>
<Label text="flex-grow" row="7" /> <Label text="flexGrow" row="7" />
<StackLayout row="7" col="1" orientation="horizontal"> <FlexboxLayout row="7" col="1" alignContent="stretch">
<Button text="0" tap="flexGrow" /> <Button text="0" tap="flexGrow" flexGrow="1" automationText="flexGrow-0" />
<Button text="1" tap="flexGrow" /> <Button text="1" tap="flexGrow" flexGrow="1" automationText="flexGrow-1" />
<Button text="2" tap="flexGrow" /> <Button text="2" tap="flexGrow" flexGrow="1" automationText="flexGrow-2" />
<Button text="3" tap="flexGrow" /> <Button text="3" tap="flexGrow" flexGrow="1" automationText="flexGrow-3" />
<Button text="4" tap="flexGrow" /> <Button text="4" tap="flexGrow" flexGrow="1" automationText="flexGrow-4" />
</StackLayout> </FlexboxLayout>
<Label text="flex-shrink" row="8" /> <Label text="flexShrink" row="8" />
<StackLayout row="8" col="1" orientation="horizontal"> <FlexboxLayout row="8" col="1" alignContent="stretch">
<Button text="0" tap="flexShrink" /> <Button text="0" tap="flexShrink" flexGrow="1" automationText="flexShrink-0" />
<Button text="1" tap="flexShrink" /> <Button text="1" tap="flexShrink" flexGrow="1" automationText="flexShrink-1" />
<Button text="2" tap="flexShrink" /> <Button text="2" tap="flexShrink" flexGrow="1" automationText="flexShrink-2" />
<Button text="3" tap="flexShrink" /> <Button text="3" tap="flexShrink" flexGrow="1" automationText="flexShrink-3" />
<Button text="4" tap="flexShrink" /> <Button text="4" tap="flexShrink" flexGrow="1" automationText="flexShrink-4" />
</StackLayout> </FlexboxLayout>
<!--<Label text="margin" row="9" /> <Label row="9" text="alignSelf" verticalAlignment="center" />
<StackLayout row="9" col="1" orientation="horizontal"> <FlexboxLayout row="9" col="1" flexWrap="wrap" alignContent="stretch">
<TextField text="{{margin}}" width="100" /> <Button text="auto" tap="alignSelf" flexGrow="1" automationText="alignSelf-auto" />
<Label text="width" /> <Button text="flex-start" tap="alignSelf" flexGrow="1" automationText="alignSelf-flex-start" />
<TextField text="{{width}}" width="100" /> <Button text="flex-end" tap="alignSelf" flexGrow="1" automationText="alignSelf-flex-end" />
<Label text="height" /> <Button text="center" tap="alignSelf" flexGrow="1" automationText="alignSelf-center" />
<TextField text="{{height}}" width="100" /> <Button text="baseline" tap="alignSelf" flexGrow="1" automationText="alignSelf-baseline" />
</StackLayout>--> <Button text="stretch" tap="alignSelf" flexGrow="1" automationText="alignSelf-stretch" />
</FlexboxLayout>
<!-- TODO: Align self -->
<Label row="10" text="flexWrapBefore" verticalAlignment="center" />
<FlexboxLayout row="10" col="1" flexWrap="wrap" alignContent="stretch">
<Button text="true" tap="flexWrapBefore" flexGrow="1" automationText="flexWrapBefore-true" />
<Button text="false" tap="flexWrapBefore" flexGrow="1" automationText="flexWrapBefore-false" />
</FlexboxLayout>
</GridLayout> </GridLayout>
<FlexboxLayout id="container" row="1" backgroundColor="white" margin="10">
<!-- TODO: horizontalAlignment and verticalAlignment should be handled somehow by treating the items with proper layout params -->
<Label text="row" backgroundColor="#EEEEEE" margin="20" padding="20" tap="select" /> <FlexboxLayout id="container" row="1" borderWidth="1" borderColor="black" margin="10">
<Label text="row-reverse" backgroundColor="#DDDDDD" fontSize="8" tap="select" /> <Label text="row" tap="select" margin="10" />
<Label text="column" backgroundColor="#CCCCCC" tap="select" /> <Label text="row-reverse" tap="select" />
<Label text="column-reverse" backgroundColor="#BBBBBB" tap="select" /> <Label text="column" tap="select" />
<Label text="row" backgroundColor="#AAAAAA" tap="select" /> <Label text="column-reverse" tap="select" />
<Label text="row-reverse" backgroundColor="#EEEEEE" fontSize="8" tap="select" /> <Label text="row" tap="select" />
<Label text="column" backgroundColor="#DDDDDD" tap="select" /> <Label text="row-reverse" tap="select" />
<Label text="column-reverse" backgroundColor="#CCCCCC" tap="select" /> <Label text="column" tap="select" />
<Label text="row" backgroundColor="#BBBBBB" tap="select" /> <Label text="column-reverse" tap="select" />
<Label text="row-reverse" backgroundColor="#AAAAAA" fontSize="8" tap="select" /> <Label text="row" tap="select" />
<Label text="column" backgroundColor="#EEEEEE" tap="select" /> <Label text="row-reverse" tap="select" />
<Label text="column-reverse" backgroundColor="#DDDDDD" tap="select" /> <Label text="column" tap="select" />
<Label text="row" backgroundColor="#CCCCCC" tap="select" /> <Label text="column-reverse" tap="select" />
<Label text="row-reverse" backgroundColor="#BBBBBB" fontSize="8" tap="select" /> <Label text="row" tap="select" />
<Label text="column" backgroundColor="#AAAAAA" tap="select" />
<Label text="column-reverse" backgroundColor="#EEEEEE" tap="select" />
<Label text="row" backgroundColor="#DDDDDD" tap="select" />
<Label text="row-reverse" backgroundColor="#CCCCCC" fontSize="8" tap="select" />
<Label text="column" backgroundColor="#BBBBBB" tap="select" />
<Label text="column-reverse" backgroundColor="#AAAAAA" tap="select" />
<Label text="row" backgroundColor="#EEEEEE" tap="select" />
<Label text="row-reverse" backgroundColor="#DDDDDD" fontSize="8" tap="select" />
<Label text="column" backgroundColor="#CCCCCC" tap="select" />
<Label text="column-reverse" backgroundColor="#BBBBBB" tap="select" />
</FlexboxLayout> </FlexboxLayout>
</GridLayout> </GridLayout>
</Page> </Page>

View File

@ -500,8 +500,8 @@ export const testJustifyContent_flexEnd_withParentPadding = test(
({root, flexbox, text1, text2, text3}) => { ({root, flexbox, text1, text2, text3}) => {
isLeftOf(text2, text3); isLeftOf(text2, text3);
isLeftOf(text1, text2); isLeftOf(text1, text2);
equal(width(flexbox) - right(text3), dipToDp(flexbox.paddingRight)); closeEnough(width(flexbox) - right(text3), dipToDp(flexbox.paddingRight));
equal(top(text3), dipToDp(flexbox.paddingTop)); closeEnough(top(text3), dipToDp(flexbox.paddingTop));
} }
); );
@ -560,8 +560,8 @@ export const testJustifyContent_spaceBetween_withPadding = test(
({root, flexbox, text1, text2, text3}) => { ({root, flexbox, text1, text2, text3}) => {
let space = width(flexbox) - width(text1) - width(text2) - width(text3) - dipToDp(padding) * 2; let space = width(flexbox) - width(text1) - width(text2) - width(text3) - dipToDp(padding) * 2;
space = space / 2; space = space / 2;
equal(left(text1), dipToDp(padding)); closeEnough(left(text1), dipToDp(padding));
equal(width(flexbox) - right(text3), dipToDp(padding)); closeEnough(width(flexbox) - right(text3), dipToDp(padding));
check(space - 1 <= left(text2) - right(text1) && left(text2) - right(text1) <= space + 1); check(space - 1 <= left(text2) - right(text1) && left(text2) - right(text1) <= space + 1);
check(space - 1 <= left(text3) - right(text2) && left(text3) - right(text2) <= space + 1); check(space - 1 <= left(text3) - right(text2) && left(text3) - right(text2) <= space + 1);
} }
@ -683,8 +683,8 @@ export const testJustifyContent_spaceBetween_flexDirection_column_withPadding =
({root, flexbox, text1, text2, text3}) => { ({root, flexbox, text1, text2, text3}) => {
let space = height(flexbox) - height(text1) - height(text2) - height(text3) - dipToDp(padding) * 2; let space = height(flexbox) - height(text1) - height(text2) - height(text3) - dipToDp(padding) * 2;
space = space / 2; space = space / 2;
equal(top(text1), dipToDp(padding)); closeEnough(top(text1), dipToDp(padding));
equal(height(flexbox) - bottom(text3), dipToDp(padding)); closeEnough(height(flexbox) - bottom(text3), dipToDp(padding));
check(space - 1 <= top(text2) - bottom(text1) && top(text2) - bottom(text1) <= space + 1); check(space - 1 <= top(text2) - bottom(text1) && top(text2) - bottom(text1) <= space + 1);
check(space - 1 <= top(text3) - bottom(text2) && top(text3) - bottom(text2) <= space + 1); check(space - 1 <= top(text3) - bottom(text2) && top(text3) - bottom(text2) <= space + 1);
} }
@ -854,7 +854,7 @@ export const testAlignContent_flexEnd_parentPadding = test(
isAbove(text1, text3); isAbove(text1, text3);
isAbove(text2, text3); isAbove(text2, text3);
equal(bottom(text3), height(flexbox) - dipToDp(flexbox.paddingBottom)); closeEnough(bottom(text3), height(flexbox) - dipToDp(flexbox.paddingBottom));
} }
); );
@ -870,7 +870,7 @@ export const testAlignContent_flexEnd_parentPadding_column = test(
isLeftOf(text2, text3); isLeftOf(text2, text3);
let { bounds1, bounds2 } = comparableBounds(text3, flexbox); let { bounds1, bounds2 } = comparableBounds(text3, flexbox);
equal(bounds1.right, bounds2.right - dipToDp(flexbox.paddingRight)); closeEnough(bounds1.right, bounds2.right - dipToDp(flexbox.paddingRight));
} }
); );
@ -1233,8 +1233,8 @@ export const testAlignItems_flexEnd_parentPadding = test(
({flexbox}) => flexbox.alignItems = AlignItems.FLEX_END, ({flexbox}) => flexbox.alignItems = AlignItems.FLEX_END,
({root, flexbox, text1, text2, text3}) => { ({root, flexbox, text1, text2, text3}) => {
isRightOf(text2, text1); isRightOf(text2, text1);
equal(bottom(text1), height(flexbox) - dipToDp(flexbox.paddingBottom)); closeEnough(bottom(text1), height(flexbox) - dipToDp(flexbox.paddingBottom));
equal(bottom(text2), height(flexbox) - dipToDp(flexbox.paddingBottom)); closeEnough(bottom(text2), height(flexbox) - dipToDp(flexbox.paddingBottom));
} }
); );
@ -1246,8 +1246,8 @@ export const testAlignItems_flexEnd_parentPadding_column = test(
}, },
({root, flexbox, text1, text2, text3}) => { ({root, flexbox, text1, text2, text3}) => {
isBelow(text2, text1); isBelow(text2, text1);
equal(right(text1), width(flexbox) - dipToDp(flexbox.paddingRight)); closeEnough(right(text1), width(flexbox) - dipToDp(flexbox.paddingRight));
equal(right(text2), width(flexbox) - dipToDp(flexbox.paddingRight)); closeEnough(right(text2), width(flexbox) - dipToDp(flexbox.paddingRight));
} }
); );
@ -1603,8 +1603,8 @@ export const testMinWidth_initial_width_less_than_minWidth = test(
noop, noop,
({root, flexbox, text1, text2, text3}) => { ({root, flexbox, text1, text2, text3}) => {
let minWidth = 100; let minWidth = 100;
equal(width(text1), dipToDp(100)); closeEnough(width(text1), dipToDp(100));
equal(width(text2), width(flexbox) - dipToDp(100)); closeEnough(width(text2), width(flexbox) - dipToDp(100));
} }
); );
@ -1621,8 +1621,8 @@ export const testMinWidth_works_as_lower_bound_shrink_to = test(
activity_minwidth_lower_bound_test, activity_minwidth_lower_bound_test,
noop, noop,
({root, flexbox, text1, text2, text3, text4}) => { ({root, flexbox, text1, text2, text3, text4}) => {
equal(width(text1), dipToDp(150)); closeEnough(width(text1), dipToDp(150));
equal(width(flexbox), width(text1) + width(text2) + width(text3) + width(text4)); closeEnough(width(flexbox), width(text1) + width(text2) + width(text3) + width(text4));
} }
); );
@ -1637,8 +1637,8 @@ export const testMinHeight_initial_height_less_than_minHeight = test(
activity_minheight_test, activity_minheight_test,
noop, noop,
({root, flexbox, text1, text2}) => { ({root, flexbox, text1, text2}) => {
equal(height(text1), dipToDp(100)); closeEnough(height(text1), dipToDp(100));
equal(height(text2), height(flexbox) - dipToDp(100)); closeEnough(height(text2), height(flexbox) - dipToDp(100));
} }
); );
@ -1655,8 +1655,8 @@ export const testMinHeight_works_as_lower_bound_shrink_to = test(
activity_minheight_lower_bound_test, activity_minheight_lower_bound_test,
noop, noop,
({root, flexbox, text1, text2, text3, text4}) => { ({root, flexbox, text1, text2, text3, text4}) => {
equal(height(text1), dipToDp(150)); closeEnough(height(text1), dipToDp(150));
equal(height(flexbox), height(text1) + height(text2) + height(text3) + height(text4)); closeEnough(height(flexbox), height(text1) + height(text2) + height(text3) + height(text4));
} }
); );
@ -1792,7 +1792,7 @@ export const testWrap_parentPadding_horizontal = test(
({flexbox, text1, text2, text3}) => { ({flexbox, text1, text2, text3}) => {
isBelow(text2, text1); isBelow(text2, text1);
isRightOf(text3, text2); isRightOf(text3, text2);
equal(height(flexbox), dipToDp(flexbox.paddingTop) + dipToDp(flexbox.paddingBottom) + height(text1) + height(text2)); closeEnough(height(flexbox), dipToDp(flexbox.paddingTop) + dipToDp(flexbox.paddingBottom) + height(text1) + height(text2));
} }
); );
@ -1810,7 +1810,7 @@ export const testWrap_parentPadding_vertical = test(
({flexbox, text1, text2, text3}) => { ({flexbox, text1, text2, text3}) => {
isRightOf(text2, text1); isRightOf(text2, text1);
isBelow(text3, text2); isBelow(text3, text2);
equal(width(flexbox), dipToDp(flexbox.paddingLeft) + dipToDp(flexbox.paddingRight) + width(text1) + width(text2)); closeEnough(width(flexbox), dipToDp(flexbox.paddingLeft) + dipToDp(flexbox.paddingRight) + width(text1) + width(text2));
} }
); );
@ -1828,7 +1828,7 @@ export const testWrap_childMargin_horizontal = test(
({flexbox, text1, text2, text3}) => { ({flexbox, text1, text2, text3}) => {
isBelow(text2, text1); isBelow(text2, text1);
isRightOf(text3, text2); isRightOf(text3, text2);
equal(height(flexbox), height(text1) + height(text2) + dipToDp(text2.marginTop) + dipToDp(text2.marginBottom)); closeEnough(height(flexbox), height(text1) + height(text2) + dipToDp(text2.marginTop) + dipToDp(text2.marginBottom));
} }
); );
@ -1891,7 +1891,7 @@ export const testWrap_childMargin_vertical = test(
isRightOf(text2, text1); isRightOf(text2, text1);
isBelow(text3, text2); isBelow(text3, text2);
// dips anyone? // dips anyone?
equal(width(flexbox), width(text1) + width(text2) + dipToDp(text2.marginLeft) + dipToDp(text2.marginRight)); closeEnough(width(flexbox), width(text1) + width(text2) + dipToDp(text2.marginLeft) + dipToDp(text2.marginRight));
} }
); );

View File

@ -3,7 +3,7 @@ import {View} from "ui/core/view";
import {PropertyMetadata} from "ui/core/proxy"; import {PropertyMetadata} from "ui/core/proxy";
import {Property, PropertyMetadataSettings, PropertyChangeData} from "ui/core/dependency-observable"; import {Property, PropertyMetadataSettings, PropertyChangeData} from "ui/core/dependency-observable";
import {registerSpecialProperty} from "ui/builder/special-properties"; import {registerSpecialProperty} from "ui/builder/special-properties";
import * as platform from "platform"; import {isAndroid} from "platform";
export type Basis = "auto" | number; export type Basis = "auto" | number;
@ -12,7 +12,7 @@ const FLEX_GROW_DEFAULT = 0.0;
const FLEX_SHRINK_DEFAULT = 1.0; const FLEX_SHRINK_DEFAULT = 1.0;
// on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call). // on Android we explicitly set propertySettings to None because android will invalidate its layout (skip unnecessary native call).
var AffectsLayout = platform.device.os === platform.platformNames.android ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout; var affectsLayout = isAndroid ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout;
export type FlexDirection = "row" | "row-reverse" | "column" | "column-reverse"; export type FlexDirection = "row" | "row-reverse" | "column" | "column-reverse";
export namespace FlexDirection { export namespace FlexDirection {
@ -142,18 +142,18 @@ function validateArgs(element: View): View {
*/ */
export abstract class FlexboxLayoutBase extends LayoutBase { export abstract class FlexboxLayoutBase extends LayoutBase {
public static flexDirectionProperty = new Property("flexDirection", "FlexboxLayout", new PropertyMetadata("row", AffectsLayout, undefined, validateFlexDirection, (args: any) => args.object.setNativeFlexDirection(args.newValue))); public static flexDirectionProperty = new Property("flexDirection", "FlexboxLayout", new PropertyMetadata("row", affectsLayout, undefined, validateFlexDirection, (args: any) => args.object.setNativeFlexDirection(args.newValue)));
public static flexWrapProperty = new Property("flexWrap", "FlexboxLayout", new PropertyMetadata("nowrap", AffectsLayout, undefined, validateFlexWrap, (args: any) => args.object.setNativeFlexWrap(args.newValue))); public static flexWrapProperty = new Property("flexWrap", "FlexboxLayout", new PropertyMetadata("nowrap", affectsLayout, undefined, validateFlexWrap, (args: any) => args.object.setNativeFlexWrap(args.newValue)));
public static justifyContentProperty = new Property("justifyContent", "FlexboxLayout", new PropertyMetadata("flex-start", AffectsLayout, undefined, validateJustifyContent, (args: any) => args.object.setNativeJustifyContent(args.newValue))); public static justifyContentProperty = new Property("justifyContent", "FlexboxLayout", new PropertyMetadata("flex-start", affectsLayout, undefined, validateJustifyContent, (args: any) => args.object.setNativeJustifyContent(args.newValue)));
public static alignItemsProperty = new Property("alignItems", "FlexboxLayout", new PropertyMetadata("stretch", AffectsLayout, undefined, validateAlignItems, (args: any) => args.object.setNativeAlignItems(args.newValue))); public static alignItemsProperty = new Property("alignItems", "FlexboxLayout", new PropertyMetadata("stretch", affectsLayout, undefined, validateAlignItems, (args: any) => args.object.setNativeAlignItems(args.newValue)));
public static alignContentProperty = new Property("alignContent", "FlexboxLayout", new PropertyMetadata("stretch", AffectsLayout, undefined, validateAlignContent, (args: any) => args.object.setNativeAlignContent(args.newValue))); public static alignContentProperty = new Property("alignContent", "FlexboxLayout", new PropertyMetadata("stretch", affectsLayout, undefined, validateAlignContent, (args: any) => args.object.setNativeAlignContent(args.newValue)));
// TODO: Validation: // TODO: Validation:
public static orderProperty = new Property("order", "FlexboxLayout", new PropertyMetadata(ORDER_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onOrderPropertyChanged(element, oldValue, newValue)))); public static orderProperty = new Property("order", "FlexboxLayout", new PropertyMetadata(ORDER_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
public static flexGrowProperty = new Property("flexGrow", "FlexboxLayout", new PropertyMetadata(FLEX_GROW_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onFlexGrowPropertyChanged(element, oldValue, newValue)))); public static flexGrowProperty = new Property("flexGrow", "FlexboxLayout", new PropertyMetadata(FLEX_GROW_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
public static flexShrinkProperty = new Property("flexShrink", "FlexboxLayout", new PropertyMetadata(FLEX_SHRINK_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onFlexShrinkPropertyChanged(element, oldValue, newValue)))); public static flexShrinkProperty = new Property("flexShrink", "FlexboxLayout", new PropertyMetadata(FLEX_SHRINK_DEFAULT, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
public static flexWrapBeforeProperty = new Property("flexWrapBefore", "FlexboxLayout", new PropertyMetadata(false, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<boolean>((flexbox, element, oldValue, newValue) => flexbox.onFlexWrapBeforePropertyChanged(element, oldValue, newValue)))) public static flexWrapBeforeProperty = new Property("flexWrapBefore", "FlexboxLayout", new PropertyMetadata(false, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
public static alignSelfProperty = new Property("alignSelf", "FlexboxLayout", new PropertyMetadata(AlignSelf.AUTO, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<AlignSelf>((flexbox, element, oldValue, newValue) => flexbox.onAlignSelfPropertyChanged(element, oldValue, newValue)))); public static alignSelfProperty = new Property("alignSelf", "FlexboxLayout", new PropertyMetadata(AlignSelf.AUTO, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler));
constructor() { constructor() {
super(); super();
@ -235,24 +235,18 @@ export abstract class FlexboxLayoutBase extends LayoutBase {
protected abstract setNativeAlignItems(alignItems: AlignItems); protected abstract setNativeAlignItems(alignItems: AlignItems);
protected abstract setNativeAlignContent(alignContent: AlignContent); protected abstract setNativeAlignContent(alignContent: AlignContent);
protected abstract onOrderPropertyChanged(element: View, oldValue: number, newValue: number): void; private static childHandler<V>(args: PropertyChangeData) {
protected abstract onFlexGrowPropertyChanged(element: View, oldValue: number, newValue: number): void; let element = args.object as View;
protected abstract onFlexShrinkPropertyChanged(element: View, oldValue: number, newValue: number): void;
protected abstract onAlignSelfPropertyChanged(element: View, oldValue: AlignSelf, newValue: AlignSelf): void;
protected abstract onFlexWrapBeforePropertyChanged(element: View, oldValue: boolean, newValue: boolean): void;
private static childHandler<V>(handler: (flexbox: FlexboxLayoutBase, element: View, oldValue: V, newValue: V) => void) {
return (data: PropertyChangeData) => {
let element = data.object as View;
if (!(element instanceof View)) { if (!(element instanceof View)) {
throw new Error("Element is not View or its descendant."); throw new Error("Element is not View or its descendant.");
} }
let flexbox = element.parent; let flexbox = element.parent;
if (flexbox instanceof FlexboxLayoutBase) { if (flexbox instanceof FlexboxLayoutBase) {
handler(flexbox, element, data.oldValue, data.newValue); flexbox.invalidate();
}
} }
} }
protected abstract invalidate();
} }
registerSpecialProperty("order", (instance, propertyValue) => { registerSpecialProperty("order", (instance, propertyValue) => {

View File

@ -8,8 +8,47 @@ import {
AlignSelf, AlignSelf,
FlexboxLayoutBase FlexboxLayoutBase
} from "./flexbox-layout-common"; } from "./flexbox-layout-common";
import {PropertyMetadata} from "ui/core/proxy";
import {PropertyChangeData} from "ui/core/dependency-observable";
import {layout} from "utils/utils"; import {layout} from "utils/utils";
function setLayoutParamsProperty(view: View, setter: (lp: org.nativescript.widgets.FlexboxLayout.LayoutParams) => void) {
let nativeView: android.view.View = view._nativeView;
if (nativeView) {
var lp = nativeView.getLayoutParams() || new org.nativescript.widgets.FlexboxLayout.LayoutParams();
if (lp instanceof org.nativescript.widgets.FlexboxLayout.LayoutParams) {
setter(lp);
nativeView.setLayoutParams(lp);
}
}
}
function onNativeOrderPropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.order = newValue);
}
function onNativeFlexGrowPropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.flexGrow = newValue);
}
function onNativeFlexShrinkPropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.flexShrink = newValue);
}
function onNativeAlignSelfPropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.alignSelf = alignSelfMap[newValue]);
}
function onNativeFlexWrapBeforePropertyChanged({object, newValue}: PropertyChangeData): void {
setLayoutParamsProperty(<View>object, lp => lp.wrapBefore = newValue);
}
(<PropertyMetadata>FlexboxLayoutBase.orderProperty.metadata).onSetNativeValue = onNativeOrderPropertyChanged;
(<PropertyMetadata>FlexboxLayoutBase.flexGrowProperty.metadata).onSetNativeValue = onNativeFlexGrowPropertyChanged;
(<PropertyMetadata>FlexboxLayoutBase.flexShrinkProperty.metadata).onSetNativeValue = onNativeFlexShrinkPropertyChanged;
(<PropertyMetadata>FlexboxLayoutBase.alignSelfProperty.metadata).onSetNativeValue = onNativeAlignSelfPropertyChanged;
(<PropertyMetadata>FlexboxLayoutBase.flexWrapBeforeProperty.metadata).onSetNativeValue = onNativeFlexWrapBeforePropertyChanged;
export * from "./flexbox-layout-common"; export * from "./flexbox-layout-common";
import FlexboxLayoutWidget = org.nativescript.widgets.FlexboxLayout; import FlexboxLayoutWidget = org.nativescript.widgets.FlexboxLayout;
@ -96,35 +135,8 @@ export class FlexboxLayout extends FlexboxLayoutBase {
this.android.setAlignContent(alignContentMap[alignContent]); this.android.setAlignContent(alignContentMap[alignContent]);
} }
protected onOrderPropertyChanged(view: View, oldValue: number, newValue: number): void { protected invalidate() {
this.setLayoutParamsProperty(view, lp => lp.order = newValue); // no operation
}
protected onFlexGrowPropertyChanged(view: View, oldValue: number, newValue: number): void {
this.setLayoutParamsProperty(view, lp => lp.flexGrow = newValue);
}
protected onFlexShrinkPropertyChanged(view: View, oldValue: number, newValue: number): void {
this.setLayoutParamsProperty(view, lp => lp.flexShrink = newValue);
}
protected onAlignSelfPropertyChanged(view: View, oldValue: AlignSelf, newValue: AlignSelf): void {
this.setLayoutParamsProperty(view, lp => lp.alignSelf = alignSelfMap[newValue]);
}
protected onFlexWrapBeforePropertyChanged(view: View, oldValue: boolean, newValue: boolean): void {
this.setLayoutParamsProperty(view, lp => lp.wrapBefore = newValue);
}
private setLayoutParamsProperty(view: View, setter: (lp: org.nativescript.widgets.FlexboxLayout.LayoutParams) => void) {
let nativeView: android.view.View = view._nativeView;
if (nativeView) {
var lp = nativeView.getLayoutParams() || new org.nativescript.widgets.FlexboxLayout.LayoutParams();
if (lp instanceof org.nativescript.widgets.FlexboxLayout.LayoutParams) {
setter(lp);
nativeView.setLayoutParams(lp);
}
}
} }
} }

View File

@ -87,8 +87,8 @@ export class FlexboxLayout extends FlexboxLayoutBase {
private _flexLines: FlexLine[] = []; private _flexLines: FlexLine[] = [];
private _childrenFrozen: boolean[]; private _childrenFrozen: boolean[];
public FlexboxLayout() { protected invalidate() {
// this.requestLayout();
} }
protected setNativeFlexDirection(flexDirection: FlexDirection) { protected setNativeFlexDirection(flexDirection: FlexDirection) {
@ -107,22 +107,6 @@ export class FlexboxLayout extends FlexboxLayoutBase {
// lint happy no-op // lint happy no-op
} }
protected onOrderPropertyChanged(element: View, oldValue: number, newValue: number): void {
// lint happy no-op
}
protected onFlexGrowPropertyChanged(element: View, oldValue: number, newValue: number): void {
// lint happy no-op
}
protected onFlexShrinkPropertyChanged(element: View, oldValue: number, newValue: number): void {
// lint happy no-op
}
protected onAlignSelfPropertyChanged(element: View, oldValue: AlignSelf, newValue: AlignSelf): void {
// lint happy no-op
}
protected onFlexWrapBeforePropertyChanged(element: View, oldValue: boolean, newValue: boolean): void {
// lint happy no-op
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
LayoutBase.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec); LayoutBase.adjustChildrenLayoutParams(this, widthMeasureSpec, heightMeasureSpec);
@ -147,13 +131,19 @@ export class FlexboxLayout extends FlexboxLayoutBase {
default: default:
throw new Error("Invalid value for the flex direction is set: " + this.flexDirection); throw new Error("Invalid value for the flex direction is set: " + this.flexDirection);
} }
this._childrenFrozen.length = 0;
} }
private _getReorderedChildAt(index: number): View { private _getReorderedChildAt(index: number): View {
let child: View;
if (index < 0 || index >= this._reorderedIndices.length) { if (index < 0 || index >= this._reorderedIndices.length) {
return null; child = null;
} else {
let reorderedIndex = this._reorderedIndices[index];
child = this.getChildAt(reorderedIndex);
} }
return this.getChildAt(this._reorderedIndices[index]); return child;
} }
public addChild(child: View) { public addChild(child: View) {
@ -169,8 +159,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
private _createReorderedIndices(viewBeforeAdded: View, indexForViewBeforeAdded: number, paramsForViewBeforeAdded: FlexboxLayout.LayoutParams): number[]; private _createReorderedIndices(viewBeforeAdded: View, indexForViewBeforeAdded: number, paramsForViewBeforeAdded: FlexboxLayout.LayoutParams): number[];
private _createReorderedIndices(): number[]; private _createReorderedIndices(): number[];
private _createReorderedIndices(viewBeforeAdded?: View, indexForViewBeforeAdded?: number, paramsForViewBeforeAdded?: FlexboxLayout.LayoutParams) private _createReorderedIndices(viewBeforeAdded?: View, indexForViewBeforeAdded?: number, paramsForViewBeforeAdded?: FlexboxLayout.LayoutParams) {
{
if (arguments.length === 0) { if (arguments.length === 0) {
let childCount = this.getChildrenCount(); let childCount = this.getChildrenCount();
let orders = this._createOrders(childCount); let orders = this._createOrders(childCount);
@ -202,7 +191,7 @@ export class FlexboxLayout extends FlexboxLayoutBase {
} }
private _sortOrdersIntoReorderedIndices(childCount: number, orders: Order[]): number[] { private _sortOrdersIntoReorderedIndices(childCount: number, orders: Order[]): number[] {
orders.sort(/* TODO: Orders... use the comparer? */); orders.sort((a, b) => a.compareTo(b));
if (!this._orderCache) { if (!this._orderCache) {
this._orderCache = []; this._orderCache = [];
} }
@ -348,11 +337,11 @@ export class FlexboxLayout extends FlexboxLayoutBase {
if (this.flexWrap !== FlexWrap.WRAP_REVERSE) { if (this.flexWrap !== FlexWrap.WRAP_REVERSE) {
let marginTop = flexLine._maxBaseline - FlexboxLayout.getBaseline(child); let marginTop = flexLine._maxBaseline - FlexboxLayout.getBaseline(child);
marginTop = Math.max(marginTop, lp.topMargin); marginTop = Math.max(marginTop, lp.topMargin);
largestHeightInLine = Math.max(largestHeightInLine, child.height + marginTop + lp.bottomMargin); largestHeightInLine = Math.max(largestHeightInLine, child.getActualSize().height + marginTop + lp.bottomMargin);
} else { } else {
let marginBottom = flexLine._maxBaseline - child.getMeasuredHeight() + FlexboxLayout.getBaseline(child); let marginBottom = flexLine._maxBaseline - child.getMeasuredHeight() + FlexboxLayout.getBaseline(child);
marginBottom = Math.max(marginBottom, lp.bottomMargin); marginBottom = Math.max(marginBottom, lp.bottomMargin);
largestHeightInLine = Math.max(largestHeightInLine, child.height + lp.topMargin + marginBottom); largestHeightInLine = Math.max(largestHeightInLine, child.getActualSize().height + lp.topMargin + marginBottom);
} }
} }
flexLine._crossSize = largestHeightInLine; flexLine._crossSize = largestHeightInLine;
@ -535,7 +524,8 @@ export class FlexboxLayout extends FlexboxLayoutBase {
} }
let sizeBeforeExpand = flexLine._mainSize; let sizeBeforeExpand = flexLine._mainSize;
let needsReexpand = false; let needsReexpand = false;
let unitSpace = (maxMainSize - flexLine._mainSize) / flexLine._totalFlexGrow; let pendingSpace = maxMainSize - flexLine._mainSize;
let unitSpace = pendingSpace / flexLine._totalFlexGrow;
flexLine._mainSize = paddingAlongMainAxis + flexLine._dividerLengthInMainSize; flexLine._mainSize = paddingAlongMainAxis + flexLine._dividerLengthInMainSize;
let accumulatedRoundError = 0; let accumulatedRoundError = 0;
for (let i = 0; i < flexLine.itemCount; i++) { for (let i = 0; i < flexLine.itemCount; i++) {
@ -549,54 +539,32 @@ export class FlexboxLayout extends FlexboxLayoutBase {
let lp = FlexboxLayout.getLayoutParams(child); let lp = FlexboxLayout.getLayoutParams(child);
if (this._isMainAxisDirectionHorizontal(flexDirection)) { if (this._isMainAxisDirectionHorizontal(flexDirection)) {
if (!this._childrenFrozen[childIndex]) { if (!this._childrenFrozen[childIndex]) {
let rawCalculatedWidth = child.getMeasuredWidth() + unitSpace * lp.flexGrow; let rawCalculatedWidth = child.getMeasuredWidth() + unitSpace * lp.flexGrow + accumulatedRoundError;
if (i === flexLine.itemCount - 1) { let roundedCalculatedWidth = Math.round(rawCalculatedWidth);
rawCalculatedWidth += accumulatedRoundError; if (roundedCalculatedWidth > lp.maxWidth) {
accumulatedRoundError = 0;
}
let newWidth = Math.round(rawCalculatedWidth);
if (newWidth > lp.maxWidth) {
needsReexpand = true; needsReexpand = true;
newWidth = lp.maxWidth; roundedCalculatedWidth = lp.maxWidth;
this._childrenFrozen[childIndex] = true; this._childrenFrozen[childIndex] = true;
flexLine._totalFlexGrow -= lp.flexGrow; flexLine._totalFlexGrow -= lp.flexGrow;
} else { } else {
accumulatedRoundError += (rawCalculatedWidth - newWidth); accumulatedRoundError = rawCalculatedWidth - roundedCalculatedWidth;
if (accumulatedRoundError > 1.0) {
newWidth += 1;
accumulatedRoundError -= 1.0;
} else if (accumulatedRoundError < -1.0) {
newWidth -= 1;
accumulatedRoundError += 1.0;
} }
} child.measure(makeMeasureSpec(roundedCalculatedWidth, EXACTLY), makeMeasureSpec(child.getMeasuredHeight(), EXACTLY));
child.measure(makeMeasureSpec(newWidth, EXACTLY), makeMeasureSpec(child.getMeasuredHeight(), EXACTLY));
} }
flexLine._mainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; flexLine._mainSize += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin;
} else { } else {
if (!this._childrenFrozen[childIndex]) { if (!this._childrenFrozen[childIndex]) {
let rawCalculatedHeight = child.getMeasuredHeight() + unitSpace * lp.flexGrow; let rawCalculatedHeight = child.getMeasuredHeight() + unitSpace * lp.flexGrow + accumulatedRoundError;
if (i === flexLine._itemCount - 1) { let roundedCalculatedHeight = Math.round(rawCalculatedHeight);
rawCalculatedHeight += accumulatedRoundError; if (roundedCalculatedHeight > lp.maxHeight) {
accumulatedRoundError = 0;
}
let newHeight = Math.round(rawCalculatedHeight);
if (newHeight > lp.maxHeight) {
needsReexpand = true; needsReexpand = true;
newHeight = lp.maxHeight; roundedCalculatedHeight = lp.maxHeight;
this._childrenFrozen[childIndex] = true; this._childrenFrozen[childIndex] = true;
flexLine._totalFlexGrow -= lp.flexGrow; flexLine._totalFlexGrow -= lp.flexGrow;
} else { } else {
accumulatedRoundError += (rawCalculatedHeight - newHeight); accumulatedRoundError = rawCalculatedHeight - roundedCalculatedHeight;
if (accumulatedRoundError > 1.0) {
newHeight += 1;
accumulatedRoundError -= 1.0;
} else if (accumulatedRoundError < -1.0) {
newHeight -= 1;
accumulatedRoundError += 1.0;
} }
} child.measure(makeMeasureSpec(child.getMeasuredWidth(), EXACTLY), makeMeasureSpec(roundedCalculatedHeight, EXACTLY));
child.measure(makeMeasureSpec(child.getMeasuredWidth(), EXACTLY), makeMeasureSpec(newHeight, EXACTLY));
} }
flexLine._mainSize += child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; flexLine._mainSize += child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin;
} }