Merge pull request #2269 from NativeScript/cankov/label-smart-layout-invalidation

Layout will not requestLayout when its text is changed if it has fixed size
This commit is contained in:
Panayot Cankov
2016-06-08 15:39:08 +03:00
5 changed files with 110 additions and 2 deletions

View File

@ -1,4 +1,4 @@
import TKUnit = require("../../TKUnit");
import * as TKUnit from "../../TKUnit";
import testModule = require("../../ui-test");
import styling = require("ui/styling");
@ -17,6 +17,13 @@ import labelTestsNative = require("./label-tests-native");
import fs = require("file-system");
import background = require("ui/styling/background");
import {StackLayout} from "ui/layouts/stack-layout";
import {GridLayout} from "ui/layouts/grid-layout";
import {isIOS} from "platform";
import {Label} from "ui/label";
import {LayoutBase} from "ui/layouts/layout-base";
import * as helper from "../helper";
export class LabelTest extends testModule.UITest<LabelModule.Label> {
public create(): LabelModule.Label {
@ -524,8 +531,77 @@ export class LabelTest extends testModule.UITest<LabelModule.Label> {
page.addCss("label { < !--Test wrong comment-- > background-color: red; }");
TKUnit.assertNotEqual(this.errorMessage, undefined);
}
private requestLayoutFixture(expectRequestLayout: boolean, setup: (label: Label) => LayoutBase): void {
if (!isIOS) {
return;
}
let label = new Label();
let host = setup(label);
host.addChild(label);
let mainPage = helper.getCurrentPage();
mainPage.content = host;
TKUnit.waitUntilReady(() => host.isLoaded);
let called = false;
label.requestLayout = () => called = true;
label.text = "Hello World";
if (expectRequestLayout) {
TKUnit.assertTrue(called, "label.requestLayout should be called.");
} else {
TKUnit.assertFalse(called, "image.requestLayout should not be called.");
}
}
public test_SettingTextWhenInFixedSizeGridShouldNotRequestLayout() {
this.requestLayoutFixture(false, () => {
let host = new GridLayout();
host.width = 100;
host.height = 100;
return host;
});
}
public test_SettingTextWhenFixedWidthAndHeightDoesNotRequestLayout() {
this.requestLayoutFixture(false, label => {
let host = new StackLayout();
label.width = 100;
label.height = 100;
return host;
});
};
public test_SettingTextWhenSizedToContentShouldInvalidate() {
this.requestLayoutFixture(true, () => {
let host = new StackLayout();
host.orientation = "horizontal";
return host;
});
};
public test_SettingTextOnSingleLineTextWhenWidthIsSizedToParentAndHeightIsSizedToContentShouldNotRequestLayout() {
this.requestLayoutFixture(false, () => {
let host = new StackLayout();
host.width = 100;
return host;
});
}
public test_SettingTextOnMultilineLineTextWhenWidthIsSizedToParentAndHeightIsSizedToContentShouldRequestLayout() {
this.requestLayoutFixture(true, label => {
label.textWrap = true;
let host = new StackLayout();
host.width = 100;
return host;
});
}
}
export function createTestCase(): LabelTest {
return new LabelTest();
}

View File

@ -57,8 +57,16 @@ class UILabelImpl extends UILabel {
}
}
enum FixedSize {
NONE = 0,
WIDTH = 1,
HEIGHT = 2,
BOTH = 3
}
export class Label extends common.Label {
private _ios: UILabel;
private _fixedSize: FixedSize;
constructor() {
super();
@ -81,6 +89,17 @@ export class Label extends common.Label {
this.style._updateTextDecoration();
this.style._updateTextTransform();
}
_requestLayoutOnTextChanged(): void {
if (this._fixedSize === FixedSize.BOTH) {
return;
}
if (this._fixedSize === FixedSize.WIDTH && !this.textWrap) {
// Single line label with fixed width will skip request layout on text change.
return;
}
super._requestLayoutOnTextChanged();
}
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
var nativeView = this._nativeView;
@ -99,6 +118,9 @@ export class Label extends common.Label {
height = Number.POSITIVE_INFINITY;
}
this._fixedSize = (widthMode === utils.layout.EXACTLY ? FixedSize.WIDTH : FixedSize.NONE)
| (heightMode === utils.layout.EXACTLY ? FixedSize.HEIGHT : FixedSize.NONE);
var nativeSize = nativeView.sizeThatFits(CGSizeMake(width, height));
var labelWidth = nativeSize.width;

View File

@ -17,7 +17,7 @@ function ensureWeakEvents() {
var textProperty = new dependencyObservable.Property(
"text",
"TextBase",
new proxy.PropertyMetadata("", dependencyObservable.PropertyMetadataSettings.AffectsLayout)
new proxy.PropertyMetadata("", dependencyObservable.PropertyMetadataSettings.None)
);
var formattedTextProperty = new dependencyObservable.Property(
@ -127,6 +127,10 @@ export class TextBase extends view.View implements definition.TextBase, formatte
public _addChildFromBuilder(name: string, value: any): void {
formattedString.FormattedString.addFormattedStringToView(this, name, value);
}
_requestLayoutOnTextChanged(): void {
this.requestLayout();
}
}
tbs.TextBaseStyler.registerHandlers()

View File

@ -49,6 +49,11 @@
//@private
_onTextPropertyChanged(data: dependencyObservable.PropertyChangeData): void;
_setFormattedTextPropertyToNative(value: any): void;
/**
* @private
* Called when the text property is changed to request layout.
*/
_requestLayoutOnTextChanged(): void;
//@endprivate
}
}

View File

@ -8,6 +8,7 @@ export class TextBase extends common.TextBase {
this.ios.text = newValue;
this.style._updateTextDecoration();
this.style._updateTextTransform();
this._requestLayoutOnTextChanged();
}
public _setFormattedTextPropertyToNative(value) {