mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-26 22:00:17 +08:00
Layout round instead of ceiling (#3833)
* Layout round instead of cailing Add helper method to layout module to convert to/from dips to px and measure the native view whiteSpace affects layout added for iOS Fix bug in switch onMeasure implementation Fix bug in cssValueToDevicePixels iOS implementation ActionBar for iOS is measured with AT_MOST modifier * Fix switch measure routine
This commit is contained in:
@ -232,24 +232,22 @@ export class ActionBar extends ActionBarBase {
|
||||
|
||||
private _navigationBarHeight: number = 0;
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number) {
|
||||
let width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
let widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
let height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
let heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
let navBarWidth = 0;
|
||||
let navBarHeight = 0;
|
||||
|
||||
let frame = this.page.frame;
|
||||
const frame = this.page.frame;
|
||||
if (frame) {
|
||||
let navBar: UIView = frame.ios.controller.navigationBar;
|
||||
if (!navBar.hidden) {
|
||||
let navBarSize = navBar.sizeThatFits(CGSizeMake(
|
||||
(widthMode === layout.UNSPECIFIED) ? Number.POSITIVE_INFINITY : width,
|
||||
(heightMode === layout.UNSPECIFIED) ? Number.POSITIVE_INFINITY : height));
|
||||
navBarWidth = layout.toDevicePixels(navBarSize.width);
|
||||
navBarHeight = layout.toDevicePixels(navBarSize.height);
|
||||
const desiredSize = layout.measureNativeView(navBar, width, widthMode, height, heightMode);
|
||||
navBarWidth = desiredSize.width;
|
||||
navBarHeight = desiredSize.height;
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,7 +274,7 @@ export class ActionBar extends ActionBarBase {
|
||||
View.layoutChild(this, this.titleView, 0, 0, right - left, this._navigationBarHeight);
|
||||
this.actionItems.getItems().forEach((actionItem) => {
|
||||
if (actionItem.actionView && actionItem.actionView.ios) {
|
||||
let measuredWidth = actionItem.actionView.getMeasuredWidth();
|
||||
let measuredWidth = actionItem.actionView.getMeasuredWidth();
|
||||
let measuredHeight = actionItem.actionView.getMeasuredHeight();
|
||||
View.layoutChild(this, actionItem.actionView, 0, 0, measuredWidth, measuredHeight);
|
||||
}
|
||||
|
@ -572,20 +572,14 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
let measureHeight = 0;
|
||||
|
||||
if (child && !child.isCollapsed) {
|
||||
let width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
let widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
let height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
let heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
child._updateEffectiveLayoutValues(parent);
|
||||
|
||||
let style = child.style;
|
||||
let horizontalMargins = child.effectiveMarginLeft + child.effectiveMarginRight;
|
||||
let verticalMargins = child.effectiveMarginTop + child.effectiveMarginBottom;
|
||||
|
||||
let childWidthMeasureSpec = ViewCommon.getMeasureSpec(width, widthMode, horizontalMargins, child.effectiveWidth, style.horizontalAlignment === "stretch");
|
||||
let childHeightMeasureSpec = ViewCommon.getMeasureSpec(height, heightMode, verticalMargins, child.effectiveHeight, style.verticalAlignment === "stretch");
|
||||
let childWidthMeasureSpec = ViewCommon.getMeasureSpec(widthMeasureSpec, horizontalMargins, child.effectiveWidth, style.horizontalAlignment === "stretch");
|
||||
let childHeightMeasureSpec = ViewCommon.getMeasureSpec(heightMeasureSpec, verticalMargins, child.effectiveHeight, style.verticalAlignment === "stretch");
|
||||
|
||||
if (traceEnabled()) {
|
||||
traceWrite(child.parent + " :measureChild: " + child + " " + layout.measureSpecToString(childWidthMeasureSpec) + ", " + layout.measureSpecToString(childHeightMeasureSpec), traceCategories.Layout);
|
||||
@ -599,7 +593,10 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
return { measuredWidth: measureWidth, measuredHeight: measureHeight };
|
||||
}
|
||||
|
||||
private static getMeasureSpec(parentLength: number, parentSpecMode: number, margins: number, childLength: number, stretched: boolean): number {
|
||||
private static getMeasureSpec(parentSpec: number, margins: number, childLength: number, stretched: boolean): number {
|
||||
const parentLength = layout.getMeasureSpecSize(parentSpec);
|
||||
const parentSpecMode = layout.getMeasureSpecMode(parentSpec);
|
||||
|
||||
let resultSize: number;
|
||||
let resultMode: number;
|
||||
|
||||
@ -607,6 +604,7 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
||||
if (childLength >= 0) {
|
||||
// If mode !== UNSPECIFIED we take the smaller of parentLength and childLength
|
||||
// Otherwise we will need to clip the view but this is not possible in all Android API levels.
|
||||
// TODO: remove Math.min(parentLength, childLength)
|
||||
resultSize = parentSpecMode === layout.UNSPECIFIED ? childLength : Math.min(parentLength, childLength);
|
||||
resultMode = layout.EXACTLY;
|
||||
}
|
||||
|
@ -370,9 +370,9 @@ export class View extends ViewCommon {
|
||||
get [horizontalAlignmentProperty.native](): HorizontalAlignment {
|
||||
return <HorizontalAlignment>org.nativescript.widgets.ViewHelper.getHorizontalAlignment(this.nativeView);
|
||||
}
|
||||
set [horizontalAlignmentProperty.native](value: HorizontalAlignment) {
|
||||
const nativeView = this.nativeView;
|
||||
const lp: any = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
set [horizontalAlignmentProperty.native](value: HorizontalAlignment) {
|
||||
const nativeView = this.nativeView;
|
||||
const lp: any = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
// Set only if params gravity exists.
|
||||
if (lp.gravity !== undefined) {
|
||||
switch (value) {
|
||||
@ -397,8 +397,8 @@ export class View extends ViewCommon {
|
||||
return <VerticalAlignment>org.nativescript.widgets.ViewHelper.getVerticalAlignment(this.nativeView);
|
||||
}
|
||||
set [verticalAlignmentProperty.native](value: VerticalAlignment) {
|
||||
const nativeView = this.nativeView;
|
||||
const lp: any = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
const nativeView = this.nativeView;
|
||||
const lp: any = nativeView.getLayoutParams() || new org.nativescript.widgets.CommonLayoutParams();
|
||||
// Set only if params gravity exists.
|
||||
if (lp.gravity !== undefined) {
|
||||
switch (value) {
|
||||
@ -562,6 +562,7 @@ interface NativePercentLengthPropertyOptions {
|
||||
setPixels: NativeSetter;
|
||||
setPercent?: NativeSetter
|
||||
}
|
||||
|
||||
function createNativePercentLengthProperty(options: NativePercentLengthPropertyOptions) {
|
||||
const { key, auto = 0 } = options;
|
||||
let setPixels, getPixels, setPercent;
|
||||
@ -590,11 +591,11 @@ function createNativePercentLengthProperty(options: NativePercentLengthPropertyO
|
||||
if (length == "auto") { // tslint:disable-line
|
||||
setPixels(this.nativeView, auto);
|
||||
} else if (typeof length === "number") {
|
||||
setPixels(this.nativeView, Math.ceil(length * layout.getDisplayDensity()));
|
||||
setPixels(this.nativeView, layout.round(layout.toDevicePixels(length)));
|
||||
} else if (length.unit == "dip") { // tslint:disable-line
|
||||
setPixels(this.nativeView, Math.ceil(length.value * layout.getDisplayDensity()));
|
||||
setPixels(this.nativeView, layout.round(layout.toDevicePixels(length.value)));
|
||||
} else if (length.unit == "px") { // tslint:disable-line
|
||||
setPixels(this.nativeView, Math.ceil(length.value));
|
||||
setPixels(this.nativeView, layout.round(length.value));
|
||||
} else if (length.unit == "%") { // tslint:disable-line
|
||||
setPercent(this.nativeView, length.value);
|
||||
} else {
|
||||
|
@ -100,35 +100,26 @@ export class View extends ViewCommon {
|
||||
}
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
let view = this.nativeView;
|
||||
const view = this.nativeView;
|
||||
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
let nativeWidth = 0;
|
||||
let nativeHeight = 0;
|
||||
|
||||
let width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
let widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
let height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
let heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
if (view) {
|
||||
if (widthMode === layout.UNSPECIFIED) {
|
||||
width = Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
if (heightMode === layout.UNSPECIFIED) {
|
||||
height = Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
let nativeSize = view.sizeThatFits(CGSizeMake(layout.toDeviceIndependentPixels(width), layout.toDeviceIndependentPixels(height)));
|
||||
nativeWidth = layout.toDevicePixels(nativeSize.width);
|
||||
nativeHeight = layout.toDevicePixels(nativeSize.height);
|
||||
const nativeSize = layout.measureNativeView(view, width, widthMode, height, heightMode);
|
||||
nativeWidth = nativeSize.width;
|
||||
nativeHeight = nativeSize.height;
|
||||
}
|
||||
|
||||
let measureWidth = Math.max(nativeWidth, this.effectiveMinWidth);
|
||||
let measureHeight = Math.max(nativeHeight, this.effectiveMinHeight);
|
||||
const measureWidth = Math.max(nativeWidth, this.effectiveMinWidth);
|
||||
const measureHeight = Math.max(nativeHeight, this.effectiveMinHeight);
|
||||
|
||||
let widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
let heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import {
|
||||
HtmlViewBase, View, layout, htmlProperty
|
||||
HtmlViewBase, View, layout, htmlProperty
|
||||
} from "./html-view-common";
|
||||
|
||||
export * from "./html-view-common";
|
||||
@ -30,29 +30,20 @@ export class HtmlView extends HtmlViewBase {
|
||||
var nativeView = this._nativeView;
|
||||
if (nativeView) {
|
||||
|
||||
let width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
let widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
const width = layout.getMeasureSpecSize(widthMeasureSpec);
|
||||
const widthMode = layout.getMeasureSpecMode(widthMeasureSpec);
|
||||
|
||||
let height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
let heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
if (widthMode === layout.UNSPECIFIED) {
|
||||
width = Number.POSITIVE_INFINITY;
|
||||
}
|
||||
const desiredSize = layout.measureNativeView(nativeView, width, widthMode, height, heightMode);
|
||||
|
||||
if (heightMode === layout.UNSPECIFIED) {
|
||||
height = Number.POSITIVE_INFINITY;
|
||||
}
|
||||
const labelWidth = Math.min(desiredSize.width, width);
|
||||
const measureWidth = Math.max(labelWidth, this.effectiveMinWidth);
|
||||
const measureHeight = Math.max(desiredSize.height, this.effectiveMinHeight);
|
||||
|
||||
let nativeSize = nativeView.sizeThatFits(CGSizeMake(width, height));
|
||||
let labelWidth = layout.toDevicePixels(nativeSize.width);
|
||||
|
||||
labelWidth = Math.min(labelWidth, width);
|
||||
let measureWidth = Math.max(labelWidth, this.effectiveMinWidth);
|
||||
let measureHeight = Math.max(layout.toDevicePixels(nativeSize.height), this.effectiveMinHeight);
|
||||
|
||||
let widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
let heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
const widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
const heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
@ -73,26 +73,18 @@ export class Label extends TextBase implements LabelDefinition {
|
||||
let height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
let heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
if (widthMode === layout.UNSPECIFIED) {
|
||||
width = Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
if (heightMode === layout.UNSPECIFIED) {
|
||||
height = Number.POSITIVE_INFINITY;
|
||||
}
|
||||
|
||||
this._fixedSize = (widthMode === layout.EXACTLY ? FixedSize.WIDTH : FixedSize.NONE)
|
||||
| (heightMode === layout.EXACTLY ? FixedSize.HEIGHT : FixedSize.NONE);
|
||||
|
||||
let nativeSize = nativeView.sizeThatFits(CGSizeMake(layout.toDeviceIndependentPixels(width), layout.toDeviceIndependentPixels(height)));
|
||||
let labelWidth = layout.toDevicePixels(nativeSize.width);
|
||||
const nativeSize = layout.measureNativeView(nativeView, width, widthMode, height, heightMode);
|
||||
let labelWidth = nativeSize.width;
|
||||
|
||||
if (this.textWrap) {
|
||||
labelWidth = Math.min(labelWidth, width);
|
||||
}
|
||||
|
||||
let measureWidth = Math.max(labelWidth, this.effectiveMinWidth);
|
||||
let measureHeight = Math.max(layout.toDevicePixels(nativeSize.height), this.effectiveMinHeight);
|
||||
let measureHeight = Math.max(nativeSize.height, this.effectiveMinHeight);
|
||||
|
||||
let widthAndState = View.resolveSizeAndState(measureWidth, width, widthMode, 0);
|
||||
let heightAndState = View.resolveSizeAndState(measureHeight, height, heightMode, 0);
|
||||
|
@ -514,7 +514,7 @@ export class Page extends PageBase {
|
||||
|
||||
if (!this._modalParent && this.frame && this.frame._getNavBarVisible(this)) {
|
||||
// Measure ActionBar with the full height.
|
||||
let actionBarSize = View.measureChild(this, this.actionBar, widthMeasureSpec, heightMeasureSpec);
|
||||
let actionBarSize = View.measureChild(this, this.actionBar, widthMeasureSpec, layout.makeMeasureSpec(height, layout.AT_MOST));
|
||||
actionBarWidth = actionBarSize.measuredWidth;
|
||||
actionBarHeight = actionBarSize.measuredHeight;
|
||||
}
|
||||
|
@ -145,19 +145,15 @@ function _flipImage(originalImage: UIImage): UIImage {
|
||||
return flippedImage;
|
||||
}
|
||||
|
||||
function cssValueToDevicePixels(source: string, total: number): number {
|
||||
let result;
|
||||
function cssValueToDevicePixels(source: string, totalPx: number): number {
|
||||
source = source.trim();
|
||||
|
||||
if (source.indexOf("px") !== -1) {
|
||||
result = parseFloat(source.replace("px", ""));
|
||||
}
|
||||
else if (source.indexOf("%") !== -1 && total > 0) {
|
||||
result = (parseFloat(source.replace("%", "")) / 100) * layout.toDeviceIndependentPixels(total);
|
||||
return parseFloat(source.replace("px", ""));
|
||||
} else if (source.indexOf("%") !== -1 && totalPx > 0) {
|
||||
return (parseFloat(source.replace("%", "")) / 100) * totalPx;
|
||||
} else {
|
||||
result = parseFloat(source);
|
||||
return layout.toDevicePixels(parseFloat(source));
|
||||
}
|
||||
return layout.toDevicePixels(result);
|
||||
}
|
||||
|
||||
function drawNonUniformBorders(nativeView: NativeView, background: Background) {
|
||||
@ -293,10 +289,10 @@ function drawClipPath(nativeView: UIView, background: Background) {
|
||||
const layerSize = layerBounds.size;
|
||||
|
||||
const bounds = {
|
||||
left: layerOrigin.x,
|
||||
top: layerOrigin.y,
|
||||
bottom: layerSize.height,
|
||||
right: layerSize.width
|
||||
left: layout.toDevicePixels(layerOrigin.x),
|
||||
top: layout.toDevicePixels(layerOrigin.y),
|
||||
bottom: layout.toDevicePixels(layerSize.height),
|
||||
right: layout.toDevicePixels(layerSize.width)
|
||||
};
|
||||
|
||||
if (bounds.right === 0 || bounds.bottom === 0) {
|
||||
|
@ -59,16 +59,16 @@ function toDevicePixelsCommon(length: PercentLength, auto: number, parentAvailab
|
||||
return auto;
|
||||
}
|
||||
if (typeof length === "number") {
|
||||
return Math.ceil(layout.getDisplayDensity() * length);
|
||||
return layout.round(layout.toDevicePixels(length));
|
||||
}
|
||||
switch (length.unit) {
|
||||
case "px":
|
||||
return Math.ceil(length.value);
|
||||
return layout.round(length.value);
|
||||
case "%":
|
||||
return Math.round(parentAvailableWidth * length.value);
|
||||
return layout.round(parentAvailableWidth * length.value);
|
||||
case "dip":
|
||||
default:
|
||||
return Math.ceil(layout.getDisplayDensity() * length.value);
|
||||
return layout.round(layout.toDevicePixels(length.value));
|
||||
}
|
||||
}
|
||||
|
||||
|
20
tns-core-modules/ui/styling/style/style.d.ts
vendored
20
tns-core-modules/ui/styling/style/style.d.ts
vendored
@ -134,14 +134,14 @@ export class Style extends Observable {
|
||||
public view: ViewBase;
|
||||
|
||||
//flexbox layout properties
|
||||
flexDirection: FlexDirection;
|
||||
flexWrap: FlexWrap;
|
||||
justifyContent: JustifyContent;
|
||||
alignItems: AlignItems;
|
||||
alignContent: AlignContent;
|
||||
order: Order;
|
||||
flexGrow: FlexGrow;
|
||||
flexShrink: FlexShrink;
|
||||
flexWrapBefore: FlexWrapBefore;
|
||||
alignSelf: AlignSelf;
|
||||
public flexDirection: FlexDirection;
|
||||
public flexWrap: FlexWrap;
|
||||
public justifyContent: JustifyContent;
|
||||
public alignItems: AlignItems;
|
||||
public alignContent: AlignContent;
|
||||
public order: Order;
|
||||
public flexGrow: FlexGrow;
|
||||
public flexShrink: FlexShrink;
|
||||
public flexWrapBefore: FlexWrapBefore;
|
||||
public alignSelf: AlignSelf;
|
||||
}
|
||||
|
@ -17,9 +17,6 @@ export class Style extends Observable implements StyleDefinition {
|
||||
super();
|
||||
}
|
||||
|
||||
// private _updateCounter = 0;
|
||||
// private _nativeSetters = new Map<Property, any>();
|
||||
|
||||
public fontInternal: Font;
|
||||
public backgroundInternal: Background;
|
||||
|
||||
@ -105,199 +102,15 @@ export class Style extends Observable implements StyleDefinition {
|
||||
public statusBarStyle: string;
|
||||
public androidStatusBarBackground: Color;
|
||||
|
||||
effectiveMinWidth: number;
|
||||
effectiveMinHeight: number;
|
||||
effectiveWidth: number;
|
||||
effectiveHeight: number;
|
||||
effectiveMarginTop: number;
|
||||
effectiveMarginRight: number;
|
||||
effectiveMarginBottom: number;
|
||||
effectiveMarginLeft: number;
|
||||
effectivePaddingTop: number;
|
||||
effectivePaddingRight: number;
|
||||
effectivePaddingBottom: number;
|
||||
effectivePaddingLeft: number;
|
||||
effectiveBorderTopWidth: number;
|
||||
effectiveBorderRightWidth: number;
|
||||
effectiveBorderBottomWidth: number;
|
||||
effectiveBorderLeftWidth: number;
|
||||
|
||||
flexDirection: FlexDirection;
|
||||
flexWrap: FlexWrap;
|
||||
justifyContent: JustifyContent;
|
||||
alignItems: AlignItems;
|
||||
alignContent: AlignContent;
|
||||
order: Order;
|
||||
flexGrow: FlexGrow;
|
||||
flexShrink: FlexShrink;
|
||||
flexWrapBefore: FlexWrapBefore;
|
||||
alignSelf: AlignSelf;
|
||||
|
||||
// public _updateTextDecoration() {
|
||||
// if (this.textDecoration !== TextDecoration.none) {
|
||||
// this._applyProperty(textDecorationProperty, this._getValue(textDecorationProperty));
|
||||
// }
|
||||
// }
|
||||
|
||||
// public _updateTextTransform() {
|
||||
// if (this._getValue(textTransformProperty) !== TextTransform.none) {
|
||||
// this._applyProperty(textTransformProperty, this._getValue(textTransformProperty));
|
||||
// }
|
||||
// }
|
||||
|
||||
// public _beginUpdate() {
|
||||
// this._updateCounter++;
|
||||
// }
|
||||
|
||||
// public _endUpdate() {
|
||||
// this._updateCounter--;
|
||||
// if (this._updateCounter < 0) {
|
||||
// throw new Error("style._endUpdate() called, but no update is in progress.");
|
||||
// }
|
||||
|
||||
// if (this._updateCounter === 0) {
|
||||
// this._nativeSetters.forEach((newValue, property, map) => { this._applyStyleProperty(property, newValue); });
|
||||
// this._nativeSetters.clear();
|
||||
// }
|
||||
// }
|
||||
|
||||
// public _resetCssValues() {
|
||||
// this.view._cancelAllAnimations();
|
||||
// resetStyleProperties(this);
|
||||
// }
|
||||
|
||||
// public _resetLocalValues() {
|
||||
// this._resetValues(ValueSource.Local);
|
||||
// }
|
||||
|
||||
// public _inheritStyleProperties(parent: View) {
|
||||
// parent.style._eachSetPropertyValue((property, value) => {
|
||||
// if (property.inheritable) {
|
||||
// // this._inheritStyleProperty(property, value);
|
||||
// this._setValue(property, value, ValueSource.Inherited);
|
||||
// }
|
||||
|
||||
// return true;
|
||||
// });
|
||||
// }
|
||||
|
||||
// public _onPropertyChanged(property: Property, oldValue: any, newValue: any) {
|
||||
// if (traceEnabled()) {
|
||||
// traceWrite(
|
||||
// "Style._onPropertyChanged view:" + this._view +
|
||||
// ", property: " + property.name +
|
||||
// ", oldValue: " + oldValue +
|
||||
// ", newValue: " + newValue, traceCategories.Style);
|
||||
// }
|
||||
|
||||
// super._onPropertyChanged(property, oldValue, newValue);
|
||||
|
||||
// this._view._checkMetadataOnPropertyChanged(property.metadata);
|
||||
|
||||
// this._applyProperty(property, newValue);
|
||||
// }
|
||||
|
||||
// public _sizeChanged() {
|
||||
// if (!this.backgroundInternal.isEmpty()) {
|
||||
// this._applyStyleProperty(backgroundInternalProperty, this.backgroundInternal);
|
||||
// }
|
||||
|
||||
// let clipPathPropertyValue = this.clipPath;
|
||||
// if (types.isString(clipPathPropertyValue) && clipPathPropertyValue !== "") {
|
||||
// this._applyStyleProperty(clipPathProperty, clipPathPropertyValue);
|
||||
// }
|
||||
// }
|
||||
|
||||
// public _syncNativeProperties() {
|
||||
// this._eachSetPropertyValue((property, value) => {
|
||||
// this._applyStyleProperty(property, value);
|
||||
// return true;
|
||||
// });
|
||||
// }
|
||||
|
||||
// private _applyProperty(property: Property, newValue: any) {
|
||||
// this._applyStyleProperty(property, newValue);
|
||||
|
||||
// // The effective value of an inheritable property has changed
|
||||
// // propagate the change down to the descendants to update their inherited properties.
|
||||
// if (property.inheritable && this._view._childrenCount > 0) {
|
||||
// this._view._eachChildView((child: View) => {
|
||||
// // child.style._inheritStyleProperty(property);
|
||||
// child.style._setValue(property, newValue, ValueSource.Inherited);
|
||||
// return true;
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
|
||||
// private _applyStyleProperty(property: Property, newValue: any) {
|
||||
// if (!this._view._shouldApplyStyleHandlers()) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// if (this._updateCounter > 0) {
|
||||
// this._nativeSetters.set(property, newValue);
|
||||
// return;
|
||||
// }
|
||||
|
||||
// let handler: definition.StylePropertyChangedHandler = getHandler(property, this._view);
|
||||
// if (!handler) {
|
||||
// if (traceEnabled()) {
|
||||
// traceWrite("No handler for property: " + property.name + " with id: " + property.id + ", view:" + this._view, traceCategories.Style);
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (traceEnabled()) {
|
||||
// traceWrite("Found handler for property: " + property.name + ", view:" + this._view, traceCategories.Style);
|
||||
// }
|
||||
|
||||
// let shouldReset = false;
|
||||
// if (property.equalityComparer) {
|
||||
// shouldReset = property.equalityComparer(newValue, property.defaultValue);
|
||||
// }
|
||||
// else {
|
||||
// shouldReset = (newValue === property.defaultValue);
|
||||
// }
|
||||
|
||||
// public _updateTextDecoration() {
|
||||
// if (this._getValue(textDecorationProperty) !== enums.TextDecoration.none) {
|
||||
// this._applyProperty(textDecorationProperty, this._getValue(textDecorationProperty));
|
||||
// }
|
||||
// }
|
||||
|
||||
// this._view._onStylePropertyChanged(property);
|
||||
// }
|
||||
// }
|
||||
|
||||
// get _nativeView(): any {
|
||||
// return this._view._nativeView;
|
||||
// }
|
||||
|
||||
// private _setShorthandProperty(name: string, value: any): void {
|
||||
// let pairs = styleProperty.getShorthandPairs(name, value);
|
||||
// if (pairs) {
|
||||
// this._beginUpdate();
|
||||
// for (let j = 0; j < pairs.length; j++) {
|
||||
// let pair = pairs[j];
|
||||
// this._setValue(pair.property, pair.value, ValueSource.Local);
|
||||
// }
|
||||
// this._endUpdate();
|
||||
// }
|
||||
// }
|
||||
//flexbox layout properties
|
||||
public flexDirection: FlexDirection;
|
||||
public flexWrap: FlexWrap;
|
||||
public justifyContent: JustifyContent;
|
||||
public alignItems: AlignItems;
|
||||
public alignContent: AlignContent;
|
||||
public order: Order;
|
||||
public flexGrow: FlexGrow;
|
||||
public flexShrink: FlexShrink;
|
||||
public flexWrapBefore: FlexWrapBefore;
|
||||
public alignSelf: AlignSelf;
|
||||
}
|
||||
|
||||
Style.prototype.effectiveMinWidth = 0;
|
||||
Style.prototype.effectiveMinHeight = 0;
|
||||
Style.prototype.effectiveWidth = 0;
|
||||
Style.prototype.effectiveHeight = 0;
|
||||
Style.prototype.effectiveMarginTop = 0;
|
||||
Style.prototype.effectiveMarginRight = 0;
|
||||
Style.prototype.effectiveMarginBottom = 0;
|
||||
Style.prototype.effectiveMarginLeft = 0;
|
||||
Style.prototype.effectivePaddingTop = 0;
|
||||
Style.prototype.effectivePaddingRight = 0;
|
||||
Style.prototype.effectivePaddingBottom = 0;
|
||||
Style.prototype.effectivePaddingLeft = 0;
|
||||
Style.prototype.effectiveBorderTopWidth = 0;
|
||||
Style.prototype.effectiveBorderRightWidth = 0;
|
||||
Style.prototype.effectiveBorderBottomWidth = 0;
|
||||
Style.prototype.effectiveBorderLeftWidth = 0;
|
||||
|
@ -26,6 +26,7 @@ class SwitchChangeHandlerImpl extends NSObject {
|
||||
};
|
||||
}
|
||||
|
||||
const zeroSize = { width: 0, height: 0 };
|
||||
export class Switch extends SwitchBase {
|
||||
private _ios: UISwitch;
|
||||
private _handler: NSObject;
|
||||
@ -52,12 +53,12 @@ export class Switch extends SwitchBase {
|
||||
|
||||
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||
// It can't be anything different from 51x31
|
||||
let nativeSize = this._nativeView.sizeThatFits(CGSizeMake(0, 0));
|
||||
let nativeSize = this._nativeView.sizeThatFits(zeroSize);
|
||||
this.width = nativeSize.width;
|
||||
this.height = nativeSize.height;
|
||||
|
||||
let widthAndState = layout.makeMeasureSpec(layout.toDevicePixels(nativeSize.width), layout.EXACTLY);
|
||||
let heightAndState = layout.makeMeasureSpec(layout.toDevicePixels(nativeSize.height), layout.EXACTLY);
|
||||
const widthAndState = Switch.resolveSizeAndState(layout.toDevicePixels(nativeSize.width), layout.toDevicePixels(51), layout.EXACTLY, 0);
|
||||
const heightAndState = Switch.resolveSizeAndState(layout.toDevicePixels(nativeSize.height), layout.toDevicePixels(31), layout.EXACTLY, 0);
|
||||
this.setMeasuredDimension(widthAndState, heightAndState);
|
||||
}
|
||||
|
||||
|
@ -311,9 +311,9 @@ export class TabView extends TabViewBase {
|
||||
const height = layout.getMeasureSpecSize(heightMeasureSpec);
|
||||
const heightMode = layout.getMeasureSpecMode(heightMeasureSpec);
|
||||
|
||||
this._tabBarHeight = TabView.measureHelper(this._ios.tabBar, width, widthMode, height, heightMode).height;
|
||||
this._tabBarHeight = layout.measureNativeView(this._ios.tabBar, width, widthMode, height, heightMode).height;
|
||||
const moreNavBarVisible = !!this._ios.moreNavigationController.navigationBar.window;
|
||||
this._navBarHeight = moreNavBarVisible ? TabView.measureHelper(this._ios.moreNavigationController.navigationBar, width, widthMode, height, heightMode).height : 0;
|
||||
this._navBarHeight = moreNavBarVisible ? layout.measureNativeView(this._ios.moreNavigationController.navigationBar, width, widthMode, height, heightMode).height : 0;
|
||||
|
||||
const density = layout.getDisplayDensity();
|
||||
let measureWidth = 0;
|
||||
@ -347,13 +347,6 @@ export class TabView extends TabViewBase {
|
||||
}
|
||||
}
|
||||
|
||||
private static measureHelper(nativeView: UIView, width: number, widthMode: number, height: number, heightMode: number): CGSize {
|
||||
const size = nativeView.sizeThatFits(CGSizeMake(
|
||||
(widthMode === layout.UNSPECIFIED) ? Number.POSITIVE_INFINITY : width,
|
||||
(heightMode === layout.UNSPECIFIED) ? Number.POSITIVE_INFINITY : height));
|
||||
return { width: layout.toDevicePixels(size.width), height: layout.toDevicePixels(size.height) };
|
||||
}
|
||||
|
||||
private _updateIOSTabBarColorsAndFonts(): void {
|
||||
if (!this.items) {
|
||||
return;
|
||||
@ -460,7 +453,7 @@ interface TabStates {
|
||||
}
|
||||
|
||||
function getTitleAttributesForStates(tabView: TabView): TabStates {
|
||||
const result: TabStates = { };
|
||||
const result: TabStates = {};
|
||||
|
||||
const font = tabView.style.fontInternal.getUIFont(UIFont.systemFontOfSize(10));
|
||||
let tabItemTextColor = tabView.style.tabTextColor;
|
||||
|
@ -245,6 +245,7 @@ export namespace WhiteSpace {
|
||||
export const whiteSpaceProperty = new CssProperty<Style, WhiteSpace>({
|
||||
name: "whiteSpace",
|
||||
cssName: "white-space",
|
||||
affectsLayout: isIOS,
|
||||
valueConverter: WhiteSpace.parse
|
||||
});
|
||||
whiteSpaceProperty.register(Style);
|
||||
|
@ -87,6 +87,18 @@ export module layout {
|
||||
text += size;
|
||||
return text;
|
||||
}
|
||||
|
||||
export function round(value: number): number {
|
||||
const res = Math.floor(value + 0.5);
|
||||
if (res !== 0) {
|
||||
return res;
|
||||
} else if (value === 0) {
|
||||
return 0;
|
||||
} else if (value > 0) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
export function isFileOrResourcePath(path: string): boolean {
|
||||
@ -123,7 +135,7 @@ export function mergeSort(arr, compareFunc) {
|
||||
|
||||
export function merge(left, right, compareFunc) {
|
||||
let result = [];
|
||||
while(left.length && right.length) {
|
||||
while (left.length && right.length) {
|
||||
if (compareFunc(left[0], right[0]) <= 0) {
|
||||
result.push(left.shift());
|
||||
} else {
|
||||
|
@ -45,6 +45,15 @@ export module layout {
|
||||
export function toDeviceIndependentPixels(value: number): number {
|
||||
return value / getDisplayDensity();
|
||||
}
|
||||
|
||||
export function measureNativeView(nativeView: any /* android.view.View */, width: number, widthMode: number, height: number, heightMode: number): { width: number, height: number } {
|
||||
const view = <android.view.View>nativeView;
|
||||
view.measure(makeMeasureSpec(width, widthMode), makeMeasureSpec(height, heightMode));
|
||||
return {
|
||||
width: view.getMeasuredWidth(),
|
||||
height: view.getMeasuredHeight()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// We are using "ad" here to avoid namespace collision with the global android object
|
||||
|
30
tns-core-modules/utils/utils.d.ts
vendored
30
tns-core-modules/utils/utils.d.ts
vendored
@ -23,6 +23,9 @@ interface CacheLayerType {
|
||||
* Utility module related to layout.
|
||||
*/
|
||||
export module layout {
|
||||
export type px = number;
|
||||
export type dip = number;
|
||||
|
||||
/**
|
||||
* Bits that provide the actual measured size.
|
||||
*/
|
||||
@ -53,7 +56,7 @@ export module layout {
|
||||
* @param size - The size component of measure specification.
|
||||
* @param mode - The mode component of measure specification.
|
||||
*/
|
||||
export function makeMeasureSpec(size: number, mode: number): number;
|
||||
export function makeMeasureSpec(px: number, mode: number): number;
|
||||
/**
|
||||
* Gets display density for the current device.
|
||||
*/
|
||||
@ -62,13 +65,34 @@ export module layout {
|
||||
* Convert value to device pixels.
|
||||
* @param value - The pixel to convert.
|
||||
*/
|
||||
export function toDevicePixels(value: number): number;
|
||||
export function toDevicePixels(value: dip): px;
|
||||
/**
|
||||
* Convert value to device independent pixels.
|
||||
* @param value - The pixel to convert.
|
||||
*/
|
||||
export function toDeviceIndependentPixels(value: number): number;
|
||||
export function toDeviceIndependentPixels(value: px): dip;
|
||||
|
||||
/**
|
||||
* Rounds value used in layout.
|
||||
* @param value to round.
|
||||
*/
|
||||
export function round(px: px): px;
|
||||
|
||||
/**
|
||||
* Converts device pixels to device independent pixes and measure the nativeView.
|
||||
* Returns the desired size of the nativeView in device pixels.
|
||||
* @param nativeView the nativeView to measure (UIView or android.view.View)
|
||||
* @param width the available width
|
||||
* @param widthMode width mode - UNSPECIFIED, EXACTLY or AT_MOST
|
||||
* @param height the available hegiht
|
||||
* @param heightMode height mode - UNSPECIFIED, EXACTLY or AT_MOST
|
||||
*/
|
||||
export function measureNativeView(nativeView: any /* UIView or android.view.View */, width: number, widthMode: number, height: number, heightMode: number): { width: number, height: number };
|
||||
|
||||
/**
|
||||
* Prints user friendly version of the measureSpec.
|
||||
* @param measureSpec the spec to print
|
||||
*/
|
||||
export function measureSpecToString(measureSpec: number): string;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,18 @@ export module layout {
|
||||
export function toDeviceIndependentPixels(value: number): number {
|
||||
return value / mainScreenScale;
|
||||
}
|
||||
|
||||
export function measureNativeView(nativeView: any /* UIView */, width: number, widthMode: number, height: number, heightMode: number): { width: number, height: number } {
|
||||
const view = <UIView>nativeView;
|
||||
const nativeSize = view.sizeThatFits({
|
||||
width: widthMode === 0 /* layout.UNSPECIFIED */ ? Number.POSITIVE_INFINITY : toDeviceIndependentPixels(width),
|
||||
height: heightMode === 0 /* layout.UNSPECIFIED */ ? Number.POSITIVE_INFINITY : toDeviceIndependentPixels(height)
|
||||
});
|
||||
|
||||
nativeSize.width = toDevicePixels(nativeSize.width);
|
||||
nativeSize.height = toDevicePixels(nativeSize.height);
|
||||
return nativeSize;
|
||||
}
|
||||
}
|
||||
|
||||
export module ios {
|
||||
|
Reference in New Issue
Block a user