feat(view): introduce LayoutChanged event on every View component (#5825)

* feat(view): introduce LayoutChanged event

* test(view): add LayoutChanged event tests

* chore(view-android): attach to onLayoutChange only if listener attached

* feat(view-android): override on/off in order to attach and detach from OnLayoutChangeListener
This commit is contained in:
Alexander Djenkov
2018-05-21 17:22:40 +03:00
committed by GitHub
parent f671f778f3
commit 0fc1547a19
8 changed files with 305 additions and 18 deletions

View File

@@ -141,6 +141,9 @@ allTests["FRAME"] = frameTests;
import * as viewTests from "./ui/view/view-tests";
allTests["VIEW"] = viewTests;
import * as viewLayoutChangedEventTests from "./ui/view/view-tests-layout-event";
allTests["VIEW-LAYOUT-EVENT"] = viewLayoutChangedEventTests;
import * as styleTests from "./ui/styling/style-tests";
allTests["STYLE"] = styleTests;

View File

@@ -37,7 +37,7 @@ export function getColor(uiColor: UIColor): Color {
return new Color(alpha, red, green, blue);
}
function clearPage(): void {
export function clearPage(): void {
let newPage = getCurrentPage();
if (!newPage) {
throw new Error("NO CURRENT PAGE!!!!");

View File

@@ -0,0 +1,210 @@
import * as commonTests from "./view-tests-common";
import { View } from "tns-core-modules/ui/core/view";
import { Button } from "tns-core-modules/ui/button";
import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout/stack-layout";
import * as helper from "../helper";
import * as TKUnit from "../../TKUnit";
import * as utils from "tns-core-modules/utils/utils";
export function test_event_LayoutChanged_GetActualSize() {
const test = function (views: Array<View>) {
let buttonLayoutChanged = false;
views[1].on(View.layoutChangedEvent, (data) => {
buttonLayoutChanged = true;
});
TKUnit.waitUntilReady(() => buttonLayoutChanged);
TKUnit.assert(views[1].getActualSize().height > 0);
TKUnit.assert(views[1].getActualSize().width > 0);
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_event_LayoutChanged_Listeners() {
const test = function (views: Array<View>) {
let stackLayoutChanged = false;
let buttonLayoutChanged = false;
views[1].on(View.layoutChangedEvent, (data) => {
buttonLayoutChanged = true;
});
TKUnit.waitUntilReady(() => buttonLayoutChanged);
TKUnit.assertFalse(views[0].hasListeners(View.layoutChangedEvent));
TKUnit.assert(views[1].hasListeners(View.layoutChangedEvent));
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_event_LayoutChanged_IsRaised() {
helper.clearPage();
let newPage = helper.getCurrentPage();
let stackLayoutChanged = false;
let buttonLayoutChanged = false;
let stackLayout = new StackLayout();
let button = new Button();
stackLayout.on(View.layoutChangedEvent, (data) => {
stackLayoutChanged = true;
});
button.on(View.layoutChangedEvent, (data) => {
buttonLayoutChanged = true;
});
stackLayout.addChild(button);
newPage.content = stackLayout;
TKUnit.waitUntilReady(() => stackLayoutChanged && buttonLayoutChanged);
TKUnit.assert(stackLayoutChanged);
TKUnit.assert(buttonLayoutChanged);
newPage.content = null;
};
export function test_event_LayoutChanged_IsRaised_StackLayout_ChildAdded() {
helper.clearPage();
let newPage = helper.getCurrentPage();
let stackLayoutChangedCount = 0;
let button1LayoutChangedCount = 0;
let button2LayoutChanged = false;
let stackLayout = new StackLayout();
// StackLayout should not be stretched in order to layout again when new button added.
stackLayout.verticalAlignment = "top";
let button1 = new Button();
let button2 = new Button();
stackLayout.on(View.layoutChangedEvent, (data) => {
stackLayoutChangedCount++;
});
button1.on(View.layoutChangedEvent, (data) => {
button1LayoutChangedCount++;
});
button2.on(View.layoutChangedEvent, (data) => {
button2LayoutChanged = true;
});
stackLayout.addChild(button1);
newPage.content = stackLayout;
TKUnit.waitUntilReady(() => stackLayout.isLoaded);
stackLayout.addChild(button2);
TKUnit.waitUntilReady(() => button2LayoutChanged);
TKUnit.assertEqual(stackLayoutChangedCount, 2);
TKUnit.assertEqual(button1LayoutChangedCount, 1);
TKUnit.assert(button2LayoutChanged);
newPage.content = null;
};
export function test_event_LayoutChanged_IsRaised_ChildMarginChanged() {
const test = function (views: Array<View>) {
let stackLayoutChanged = false;
let buttonLayoutChanged = false;
views[1].on(View.layoutChangedEvent, (data) => {
stackLayoutChanged = true;
});
views[2].on(View.layoutChangedEvent, (data) => {
buttonLayoutChanged = true;
});
(<Button>views[2]).marginTop = 50;
TKUnit.waitUntilReady(() => buttonLayoutChanged);
TKUnit.assert(stackLayoutChanged);
TKUnit.assert(buttonLayoutChanged);
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_event_LayoutChanged_IsRaised_ParentMarginChanged() {
const test = function (views: Array<View>) {
let stackLayoutChanged = false;
let buttonLayoutChanged = false;
views[1].on(View.layoutChangedEvent, (data) => {
stackLayoutChanged = true;
});
views[2].on(View.layoutChangedEvent, (data) => {
buttonLayoutChanged = true;
});
(<Button>views[2]).marginTop = 50;
TKUnit.waitUntilReady(() => buttonLayoutChanged);
TKUnit.assert(stackLayoutChanged);
TKUnit.assert(buttonLayoutChanged);
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_event_LayoutChanged_IsNotRaised_TransformChanged() {
const test = function (views: Array<View>) {
let stackLayoutChangedCount = 0;
let buttonLayoutChangedCount = 0;
const button = <Button>views[2];
views[1].on(View.layoutChangedEvent, (data) => {
stackLayoutChangedCount++;
});
button.on(View.layoutChangedEvent, (data) => {
buttonLayoutChangedCount++;
});
button.translateX += 50;
button.translateY += 50;
button.rotate += 50;
button.height = 200;
TKUnit.waitUntilReady(() => button.height === 200);
TKUnit.assertEqual(stackLayoutChangedCount, 1);
TKUnit.assertEqual(buttonLayoutChangedCount, 1);
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};
export function test_event_LayoutChanged_IsRaised_StackLayout_SizeChanged() {
const test = function (views: Array<View>) {
let stackLayoutChanged = false;
let buttonLayoutChanged = false;
views[1].on(View.layoutChangedEvent, (data) => {
stackLayoutChanged = true;
});
views[2].on(View.layoutChangedEvent, (data) => {
buttonLayoutChanged = true;
});
(<StackLayout>views[1]).height = 100;
TKUnit.waitUntilReady(() => buttonLayoutChanged);
TKUnit.assert(stackLayoutChanged);
TKUnit.assert(buttonLayoutChanged);
};
helper.do_PageTest_WithStackLayout_AndButton(test);
};

View File

@@ -1,15 +1,16 @@
import * as commonTests from "./view-tests-common";
import * as view from "tns-core-modules/ui/core/view";
import * as grid from "tns-core-modules/ui/layouts/grid-layout";
import * as color from "tns-core-modules/color";
import { View } from "tns-core-modules/ui/core/view";
import { Button } from "tns-core-modules/ui/button";
import { GridLayout } from "tns-core-modules/ui/layouts/grid-layout";
import { Color } from "tns-core-modules/color";
import * as helper from "../helper";
import * as TKUnit from "../../TKUnit";
import * as button from "tns-core-modules/ui/button";
import * as utils from "tns-core-modules/utils/utils";
global.moduleMerge(commonTests, exports);
class MyGrid extends grid.GridLayout {
class MyGrid extends GridLayout {
public backgroundDrawCount: number = 0;
_redrawNativeBackground(background: any) {
@@ -18,33 +19,33 @@ class MyGrid extends grid.GridLayout {
}
}
export function getUniformNativeBorderWidth(v: view.View): number {
export function getUniformNativeBorderWidth(v: View): number {
return utils.layout.toDevicePixels((<UIView>v.ios).layer.borderWidth);
}
export function checkUniformNativeBorderColor(v: view.View): boolean {
if (v.borderColor instanceof color.Color) {
return (<UIView>v.ios).layer.borderColor === (<color.Color>v.borderColor).ios.CGColor;
export function checkUniformNativeBorderColor(v: View): boolean {
if (v.borderColor instanceof Color) {
return (<UIView>v.ios).layer.borderColor === (<Color>v.borderColor).ios.CGColor;
}
return undefined;
}
export function getUniformNativeCornerRadius(v: view.View): number {
export function getUniformNativeCornerRadius(v: View): number {
return utils.layout.toDevicePixels((<UIView>v.ios).layer.cornerRadius);
}
export function checkNativeBackgroundColor(v: view.View): boolean {
export function checkNativeBackgroundColor(v: View): boolean {
if (v.ios instanceof UILabel) {
var cgColor1 = (<UILabel>v.ios).layer.backgroundColor;
var cgColor2 = (<UIColor>(<color.Color>v.backgroundColor).ios).CGColor;
var cgColor2 = (<UIColor>(<Color>v.backgroundColor).ios).CGColor;
return v.backgroundColor && !!CGColorEqualToColor(cgColor1, cgColor2);
}
return v.backgroundColor && (<UIView>v.ios).backgroundColor.isEqual((<color.Color>v.backgroundColor).ios);
return v.backgroundColor && (<UIView>v.ios).backgroundColor.isEqual((<Color>v.backgroundColor).ios);
}
export function checkNativeBackgroundImage(v: view.View): boolean {
export function checkNativeBackgroundImage(v: View): boolean {
return (<UIView>v.ios).backgroundColor !== undefined;
}
@@ -53,7 +54,7 @@ export function testBackgroundInternalChangedOnceOnResize() {
let root = helper.getCurrentPage();
let layout = new MyGrid();
layout.className = "myClass";
layout.backgroundColor = new color.Color(255, 255, 0, 0);
layout.backgroundColor = new Color(255, 255, 0, 0);
root.css = ".myClass { background-image: url('~/logo.png') }";
root.content = layout;
@@ -82,7 +83,7 @@ export function testBackgroundInternalChangedOnceOnResize() {
}
export function test_automation_text_set_to_native() {
var newButton = new button.Button();
var newButton = new Button();
newButton.automationText = "Button1";
helper.getCurrentPage().content = newButton;
TKUnit.assertEqual((<UIView>newButton.ios).accessibilityIdentifier, "Button1", "accessibilityIdentifier not set to native view.");