mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-17 21:01:34 +08:00
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:
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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()
|
||||
|
5
tns-core-modules/ui/text-base/text-base.d.ts
vendored
5
tns-core-modules/ui/text-base/text-base.d.ts
vendored
@ -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
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
Reference in New Issue
Block a user