mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-17 12:57:42 +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 testModule = require("../../ui-test");
|
||||||
import styling = require("ui/styling");
|
import styling = require("ui/styling");
|
||||||
|
|
||||||
@ -17,6 +17,13 @@ import labelTestsNative = require("./label-tests-native");
|
|||||||
import fs = require("file-system");
|
import fs = require("file-system");
|
||||||
import background = require("ui/styling/background");
|
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> {
|
export class LabelTest extends testModule.UITest<LabelModule.Label> {
|
||||||
|
|
||||||
public create(): 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; }");
|
page.addCss("label { < !--Test wrong comment-- > background-color: red; }");
|
||||||
TKUnit.assertNotEqual(this.errorMessage, undefined);
|
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 {
|
export function createTestCase(): LabelTest {
|
||||||
return new 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 {
|
export class Label extends common.Label {
|
||||||
private _ios: UILabel;
|
private _ios: UILabel;
|
||||||
|
private _fixedSize: FixedSize;
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
@ -82,6 +90,17 @@ export class Label extends common.Label {
|
|||||||
this.style._updateTextTransform();
|
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 {
|
public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void {
|
||||||
var nativeView = this._nativeView;
|
var nativeView = this._nativeView;
|
||||||
if (nativeView) {
|
if (nativeView) {
|
||||||
@ -99,6 +118,9 @@ export class Label extends common.Label {
|
|||||||
height = Number.POSITIVE_INFINITY;
|
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 nativeSize = nativeView.sizeThatFits(CGSizeMake(width, height));
|
||||||
var labelWidth = nativeSize.width;
|
var labelWidth = nativeSize.width;
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ function ensureWeakEvents() {
|
|||||||
var textProperty = new dependencyObservable.Property(
|
var textProperty = new dependencyObservable.Property(
|
||||||
"text",
|
"text",
|
||||||
"TextBase",
|
"TextBase",
|
||||||
new proxy.PropertyMetadata("", dependencyObservable.PropertyMetadataSettings.AffectsLayout)
|
new proxy.PropertyMetadata("", dependencyObservable.PropertyMetadataSettings.None)
|
||||||
);
|
);
|
||||||
|
|
||||||
var formattedTextProperty = new dependencyObservable.Property(
|
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 {
|
public _addChildFromBuilder(name: string, value: any): void {
|
||||||
formattedString.FormattedString.addFormattedStringToView(this, name, value);
|
formattedString.FormattedString.addFormattedStringToView(this, name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_requestLayoutOnTextChanged(): void {
|
||||||
|
this.requestLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tbs.TextBaseStyler.registerHandlers()
|
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
|
//@private
|
||||||
_onTextPropertyChanged(data: dependencyObservable.PropertyChangeData): void;
|
_onTextPropertyChanged(data: dependencyObservable.PropertyChangeData): void;
|
||||||
_setFormattedTextPropertyToNative(value: any): void;
|
_setFormattedTextPropertyToNative(value: any): void;
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
* Called when the text property is changed to request layout.
|
||||||
|
*/
|
||||||
|
_requestLayoutOnTextChanged(): void;
|
||||||
//@endprivate
|
//@endprivate
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,6 +8,7 @@ export class TextBase extends common.TextBase {
|
|||||||
this.ios.text = newValue;
|
this.ios.text = newValue;
|
||||||
this.style._updateTextDecoration();
|
this.style._updateTextDecoration();
|
||||||
this.style._updateTextTransform();
|
this.style._updateTextTransform();
|
||||||
|
this._requestLayoutOnTextChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public _setFormattedTextPropertyToNative(value) {
|
public _setFormattedTextPropertyToNative(value) {
|
||||||
|
Reference in New Issue
Block a user