mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 02:54:11 +08:00
Flexbox ios initial commit
Items now appear, but they should initially shrink and they don't Add 15-ish tests for flexbox layout Port reasonable flexbox test set Fixing issues, adding unit tests Moved from .tsx to .ts and used our ui/builder.parse
This commit is contained in:
@ -62,6 +62,7 @@ allTests["WRAPLAYOUT"] = require("./ui/layouts/wrap-layout-tests");
|
||||
allTests["ABSOLUTELAYOUT"] = require("./ui/layouts/absolute-layout-tests");
|
||||
allTests["GRIDLAYOUT"] = require("./ui/layouts/grid-layout-tests");
|
||||
allTests["STACKLAYOUT"] = require("./ui/layouts/stack-layout-tests");
|
||||
allTests["FLEXBOXLAYOUT"] = require("./ui/layouts/flexbox-layout-tests");
|
||||
allTests["STYLE-PROPERTIES"] = require("./ui/styling/style-properties-tests");
|
||||
allTests["FRAME"] = require("./ui/frame/frame-tests");
|
||||
allTests["VIEW"] = require("./ui/view/view-tests");
|
||||
|
1901
tests/app/ui/layouts/flexbox-layout-tests.ts
Normal file
1901
tests/app/ui/layouts/flexbox-layout-tests.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -10,7 +10,9 @@
|
||||
"experimentalDecorators": true,
|
||||
"diagnostics": true,
|
||||
"sourceMap": true,
|
||||
"noLib": true
|
||||
"noLib": true,
|
||||
"jsx": "react",
|
||||
"reactNamespace": "UIBuilder"
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
|
@ -727,6 +727,12 @@ export class View extends ProxyObject implements definition.View {
|
||||
return this._measuredHeight & utils.layout.MEASURED_SIZE_MASK;
|
||||
}
|
||||
|
||||
public getMeasuredState(): number {
|
||||
return (this._measuredWidth & utils.layout.MEASURED_STATE_MASK)
|
||||
| ((this._measuredHeight >> utils.layout.MEASURED_HEIGHT_STATE_SHIFT)
|
||||
& (utils.layout.MEASURED_STATE_MASK >> utils.layout.MEASURED_HEIGHT_STATE_SHIFT));
|
||||
}
|
||||
|
||||
public setMeasuredDimension(measuredWidth: number, measuredHeight: number): void {
|
||||
this._measuredWidth = measuredWidth;
|
||||
this._measuredHeight = measuredHeight;
|
||||
@ -786,6 +792,10 @@ export class View extends ProxyObject implements definition.View {
|
||||
return Math.round(result + 0.499) | (childMeasuredState & utils.layout.MEASURED_STATE_MASK);
|
||||
}
|
||||
|
||||
public static combineMeasuredStates(curState: number, newState): number {
|
||||
return curState | newState;
|
||||
}
|
||||
|
||||
public static layoutChild(parent: View, child: View, left: number, top: number, right: number, bottom: number): void {
|
||||
if (!child || !child._isVisible) {
|
||||
return;
|
||||
|
@ -12,6 +12,8 @@ import background = require("ui/styling/background");
|
||||
import {CommonLayoutParams} from "ui/styling/style";
|
||||
import {device} from "platform";
|
||||
|
||||
var flexbox;
|
||||
|
||||
global.moduleMerge(viewCommon, exports);
|
||||
|
||||
var ANDROID = "_android";
|
||||
@ -607,6 +609,13 @@ export class ViewStyler implements style.Styler {
|
||||
lp.rightMargin = Math.round(params.rightMargin * utils.layout.getDisplayDensity());
|
||||
lp.bottomMargin = Math.round(params.bottomMargin * utils.layout.getDisplayDensity());
|
||||
lp.gravity = gravity;
|
||||
|
||||
if (lp instanceof org.nativescript.widgets.FlexboxLayout.LayoutParams) {
|
||||
if (!flexbox) {
|
||||
flexbox = require("ui/layouts/flexbox-layout");
|
||||
}
|
||||
flexbox._setAndroidLayoutParams(lp, view);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let layoutParams: any = lp;
|
||||
|
4
tns-core-modules/ui/core/view.d.ts
vendored
4
tns-core-modules/ui/core/view.d.ts
vendored
@ -394,6 +394,8 @@ declare module "ui/core/view" {
|
||||
*/
|
||||
public getMeasuredHeight(): number;
|
||||
|
||||
public getMeasuredState(): number;
|
||||
|
||||
/**
|
||||
* Call this when something has changed which has invalidated the layout of this view. This will schedule a layout pass of the view tree.
|
||||
*/
|
||||
@ -462,6 +464,8 @@ declare module "ui/core/view" {
|
||||
*/
|
||||
public static resolveSizeAndState(size: number, specSize: number, specMode: number, childMeasuredState: number): number;
|
||||
|
||||
public static combineMeasuredStates(curState: number, newState): number;
|
||||
|
||||
/**
|
||||
* Returns the child view with the specified id.
|
||||
*/
|
||||
|
@ -7,6 +7,10 @@ import * as platform from "platform";
|
||||
|
||||
export type Basis = "auto" | number;
|
||||
|
||||
const ORDER_DEFAULT = 1;
|
||||
const FLEX_GROW_DEFAULT = 0.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).
|
||||
var AffectsLayout = platform.device.os === platform.platformNames.android ? PropertyMetadataSettings.None : PropertyMetadataSettings.AffectsLayout;
|
||||
|
||||
@ -63,6 +67,11 @@ let validJustifyContent = {
|
||||
"space-around": true
|
||||
}
|
||||
|
||||
export type FlexBasisPercent = number;
|
||||
export namespace FlexBasisPercent {
|
||||
export const DEFAULT: number = -1;
|
||||
}
|
||||
|
||||
function validateJustifyContent(value: any): boolean {
|
||||
return value in validJustifyContent;
|
||||
}
|
||||
@ -140,10 +149,11 @@ export abstract class FlexboxLayoutBase extends LayoutBase {
|
||||
public static alignContentProperty = new Property("alignContent", "FlexboxLayout", new PropertyMetadata("stretch", AffectsLayout, undefined, validateAlignContent, (args: any) => args.object.setNativeAlignContent(args.newValue)));
|
||||
|
||||
// TODO: Validation:
|
||||
public static orderProperty = new Property("order", "FlexboxLayout", new PropertyMetadata(1, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onOrderPropertyChanged(element, oldValue, newValue))));
|
||||
public static flexGrowProperty = new Property("flexGrow", "FlexboxLayout", new PropertyMetadata(0, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onFlexGrowPropertyChanged(element, oldValue, newValue))));
|
||||
public static flexShrinkProperty = new Property("flexShrink", "FlexboxLayout", new PropertyMetadata(1, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<number>((flexbox, element, oldValue, newValue) => flexbox.onFlexShrinkPropertyChanged(element, oldValue, newValue))));
|
||||
public static alignSelfProperty = new Property("alignSelf", "FlexboxLayout", new PropertyMetadata(-1, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<AlignSelf>((flexbox, element, oldValue, newValue) => flexbox.onAlignSelfPropertyChanged(element, oldValue, newValue))));
|
||||
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 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 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 flexWrapBeforeProperty = new Property("flexWrapBefore", "FlexboxLayout", new PropertyMetadata(false, PropertyMetadataSettings.None, FlexboxLayoutBase.childHandler<boolean>((flexbox, element, oldValue, newValue) => flexbox.onFlexWrapBeforePropertyChanged(element, oldValue, newValue))))
|
||||
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))));
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
@ -177,10 +187,10 @@ export abstract class FlexboxLayoutBase extends LayoutBase {
|
||||
this._setValue(FlexboxLayoutBase.alignItemsProperty, value);
|
||||
}
|
||||
|
||||
get alignContent(): AlignItems {
|
||||
get alignContent(): AlignContent {
|
||||
return this._getValue(FlexboxLayoutBase.alignContentProperty);
|
||||
}
|
||||
set alignContent(value: AlignItems) {
|
||||
set alignContent(value: AlignContent) {
|
||||
this._setValue(FlexboxLayoutBase.alignContentProperty, value);
|
||||
}
|
||||
|
||||
@ -212,8 +222,11 @@ export abstract class FlexboxLayoutBase extends LayoutBase {
|
||||
return validateArgs(view)._getValue(FlexboxLayoutBase.alignSelfProperty);
|
||||
}
|
||||
|
||||
protected onOrderPropertyChanged(element: View, oldValue: number, newValue: number): void {
|
||||
console.log("order changed: " + newValue + " " + element);
|
||||
public static setFlexWrapBefore(view: View, wrap: boolean) {
|
||||
view._setValue(FlexboxLayoutBase.flexWrapBeforeProperty, wrap);
|
||||
}
|
||||
public static getFlexWrapBefore(view: View): boolean {
|
||||
return view._getValue(FlexboxLayoutBase.flexWrapBeforeProperty);
|
||||
}
|
||||
|
||||
protected abstract setNativeFlexDirection(flexDirection: FlexDirection);
|
||||
@ -222,17 +235,11 @@ export abstract class FlexboxLayoutBase extends LayoutBase {
|
||||
protected abstract setNativeAlignItems(alignItems: AlignItems);
|
||||
protected abstract setNativeAlignContent(alignContent: AlignContent);
|
||||
|
||||
protected onFlexGrowPropertyChanged(element: View, oldValue: number, newValue: number): void {
|
||||
console.log("flex-grow changed: " + newValue + " " + element);
|
||||
}
|
||||
|
||||
protected onFlexShrinkPropertyChanged(element: View, oldValue: number, newValue: number): void {
|
||||
console.log("flex-shrink changed: " + newValue + " " + element);
|
||||
}
|
||||
|
||||
protected onAlignSelfPropertyChanged(element: View, oldValue: AlignSelf, newValue: AlignSelf): void {
|
||||
console.log("align-self changed: " + newValue + " " + element);
|
||||
}
|
||||
protected abstract onOrderPropertyChanged(element: View, oldValue: number, newValue: number): void;
|
||||
protected abstract onFlexGrowPropertyChanged(element: View, oldValue: number, newValue: number): void;
|
||||
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) => {
|
||||
@ -260,4 +267,7 @@ registerSpecialProperty("flexShrink", (instance, propertyValue) => {
|
||||
registerSpecialProperty("alignSelf", (instance, propertyValue) => {
|
||||
FlexboxLayoutBase.setAlignSelf(instance, propertyValue);
|
||||
});
|
||||
registerSpecialProperty("flexWrapBefore", (instance, propertyValue) => {
|
||||
FlexboxLayoutBase.setFlexWrapBefore(instance, propertyValue);
|
||||
});
|
||||
// No flex-basis in our implementation.
|
@ -8,6 +8,7 @@ import {
|
||||
AlignSelf,
|
||||
FlexboxLayoutBase
|
||||
} from "./flexbox-layout-common";
|
||||
import {layout} from "utils/utils";
|
||||
|
||||
export * from "./flexbox-layout-common";
|
||||
|
||||
@ -65,7 +66,6 @@ export class FlexboxLayout extends FlexboxLayoutBase {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
console.log("New FlexBoxLayout!");
|
||||
}
|
||||
|
||||
get android(): FlexboxLayoutWidget { return this._layout; }
|
||||
@ -77,56 +77,63 @@ export class FlexboxLayout extends FlexboxLayoutBase {
|
||||
|
||||
protected setNativeFlexDirection(flexDirection: FlexDirection) {
|
||||
let value = flexDirectionMap[flexDirection];
|
||||
console.log("setNativeFlexDirection: " + flexDirection + " -> " + value);
|
||||
this.android.setFlexDirection(value);
|
||||
}
|
||||
|
||||
protected setNativeFlexWrap(flexWrap: FlexWrap) {
|
||||
console.log("flexWrap: " + flexWrap);
|
||||
this.android.setFlexWrap(flexWrapMap[flexWrap]);
|
||||
}
|
||||
|
||||
protected setNativeJustifyContent(justifyContent: JustifyContent) {
|
||||
console.log("setNativeJustifyContent: " + justifyContent);
|
||||
this.android.setJustifyContent(justifyContentMap[justifyContent]);
|
||||
}
|
||||
|
||||
protected setNativeAlignItems(alignItems: AlignItems) {
|
||||
console.log("setNativeAlignItems: " + alignItems);
|
||||
this.android.setAlignItems(alignItemsMap[alignItems]);
|
||||
}
|
||||
|
||||
protected setNativeAlignContent(alignContent: AlignContent) {
|
||||
console.log("setNativeAlignContent: " + alignContent);
|
||||
this.android.setAlignContent(alignContentMap[alignContent]);
|
||||
}
|
||||
|
||||
protected onOrderPropertyChanged(view: View, oldValue: number, newValue: number): void {
|
||||
console.log("order changed: " + newValue + " " + view);
|
||||
this.setLayoutParamsProperty(view, lp => lp.order = newValue);
|
||||
}
|
||||
|
||||
protected onFlexGrowPropertyChanged(view: View, oldValue: number, newValue: number): void {
|
||||
console.log("flex-grow changed: " + newValue + " " + view);
|
||||
this.setLayoutParamsProperty(view, lp => lp.flexGrow = newValue);
|
||||
}
|
||||
|
||||
protected onFlexShrinkPropertyChanged(view: View, oldValue: number, newValue: number): void {
|
||||
console.log("flex-shrink changed: " + newValue + " " + view);
|
||||
this.setLayoutParamsProperty(view, lp => lp.flexShrink = newValue);
|
||||
}
|
||||
|
||||
protected onAlignSelfPropertyChanged(view: View, oldValue: AlignSelf, newValue: AlignSelf): void {
|
||||
console.log("align-self changed: " + newValue + " " + view);
|
||||
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;
|
||||
var lp = nativeView.getLayoutParams() || new org.nativescript.widgets.FlexboxLayout.LayoutParams();
|
||||
if (lp instanceof org.nativescript.widgets.FlexboxLayout.LayoutParams) {
|
||||
setter(lp);
|
||||
nativeView.setLayoutParams(lp);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function _setAndroidLayoutParams(lp: org.nativescript.widgets.FlexboxLayout.LayoutParams, view: View) {
|
||||
lp.order = FlexboxLayout.getOrder(view);
|
||||
lp.flexGrow = FlexboxLayout.getFlexGrow(view);
|
||||
lp.flexShrink = FlexboxLayout.getFlexShrink(view);
|
||||
lp.alignSelf = alignSelfMap[FlexboxLayout.getAlignSelf(view)];
|
||||
lp.wrapBefore = FlexboxLayout.getFlexWrapBefore(view);
|
||||
lp.minWidth = layout.toDevicePixels(view.minWidth);
|
||||
lp.minHeight = layout.toDevicePixels(view.minHeight);
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
declare module "ui/layouts/flexbox-layout" {
|
||||
|
||||
import {View} from "ui/core/view";
|
||||
import {LayoutBase} from "ui/layouts/layout-base";
|
||||
import {PropertyMetadata} from "ui/core/proxy";
|
||||
|
||||
export type FlexDirection = "row" | "row-reverse" | "column" | "column-reverse";
|
||||
export namespace FlexDirection {
|
||||
@ -55,7 +57,18 @@ declare module "ui/layouts/flexbox-layout" {
|
||||
export const STRETCH: "stretch";
|
||||
}
|
||||
|
||||
export class FlexboxLayout {
|
||||
export class FlexboxLayout extends LayoutBase {
|
||||
public static flexDirectionProperty: PropertyMetadata;
|
||||
public static flexWrapProperty: PropertyMetadata;
|
||||
public static justifyContentProperty: PropertyMetadata;
|
||||
public static alignItemsProperty: PropertyMetadata;
|
||||
|
||||
public flexDirection: FlexDirection;
|
||||
public flexWrap: FlexWrap;
|
||||
public justifyContent: JustifyContent;
|
||||
public alignItems: AlignItems;
|
||||
public alignContent: AlignContent;
|
||||
|
||||
public static setOrder(view: View, order: number);
|
||||
public static getOrder(view: View): number;
|
||||
|
||||
@ -67,5 +80,8 @@ declare module "ui/layouts/flexbox-layout" {
|
||||
|
||||
public static setAlignSelf(view: View, align: AlignSelf);
|
||||
public static getAlignSelf(view: View): AlignSelf;
|
||||
|
||||
public static setFlexWrapBefore(view: View, wrap: boolean);
|
||||
public static getFlexWrapBefore(view: View): boolean;
|
||||
}
|
||||
}
|
6
tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.internal.d.ts
vendored
Normal file
6
tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.internal.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
//@private
|
||||
declare module "ui/layouts/flex-box" {
|
||||
import {View} from "ui/core/view";
|
||||
export function _setAndroidLayoutParams(lp: any /* org.nativescript.widgets.FlexboxLayout.LayoutParams */, view: View);
|
||||
}
|
||||
//@endprivate
|
1448
tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts
Normal file
1448
tns-core-modules/ui/layouts/flexbox-layout/flexbox-layout.ios.ts
Normal file
File diff suppressed because it is too large
Load Diff
@ -21,4 +21,4 @@ export class Layout extends layoutBase.LayoutBase implements definition.Layout {
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
// Don't call super because it will measure the native element.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ export module layout {
|
||||
export var EXACTLY = 1 << MODE_SHIFT;
|
||||
export var AT_MOST = 2 << MODE_SHIFT;
|
||||
|
||||
export var MEASURED_HEIGHT_STATE_SHIFT = 0x00000010; /* 16 */
|
||||
export var MEASURED_STATE_TOO_SMALL = 0x01000000;
|
||||
export var MEASURED_STATE_MASK = 0xff000000;
|
||||
export var MEASURED_SIZE_MASK = 0x00ffffff;
|
||||
|
1
tns-core-modules/utils/utils.d.ts
vendored
1
tns-core-modules/utils/utils.d.ts
vendored
@ -28,6 +28,7 @@
|
||||
/**
|
||||
* Bits that provide the actual measured size.
|
||||
*/
|
||||
export var MEASURED_HEIGHT_STATE_SHIFT: number;
|
||||
export var MEASURED_SIZE_MASK: number;
|
||||
export var MEASURED_STATE_MASK: number;
|
||||
export var MEASURED_STATE_TOO_SMALL: number;
|
||||
|
@ -305,6 +305,9 @@
|
||||
public flexGrow: number;
|
||||
public flexShrink: number;
|
||||
public alignSelf: number;
|
||||
public wrapBefore: boolean;
|
||||
public minWidth: number;
|
||||
public minHeight: number;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,6 +10,8 @@
|
||||
"experimentalDecorators": true,
|
||||
"diagnostics": true,
|
||||
"sourceMap": true,
|
||||
"jsx": "react",
|
||||
"reactNamespace": "UIBuilder",
|
||||
"lib": [
|
||||
"es2016"
|
||||
]
|
||||
|
Reference in New Issue
Block a user