Avoid applying CSS multiple times (#4784)

* Move the applyStyleFromScope to onLoaded, when the views are created and id or className properties are set the CSS selectors are queried and applied multiple times

* Condense the changes when applying properties
This commit is contained in:
Panayot Cankov
2017-09-25 18:32:00 +03:00
committed by SvetoslavTsenov
parent b0577728be
commit 6d7c1ff295
25 changed files with 536 additions and 524 deletions

View File

@@ -359,7 +359,7 @@ function showReportPage(finalMessage: string) {
setTimeout(() => {
messageContainer.dismissSoftInput();
(<android.view.View>messageContainer.nativeViewProtected).scrollTo(0, 0);
});
}, 10);
}
}

View File

@@ -1,7 +1,7 @@
import * as helper from "../helper";
import * as btnCounter from "./pages/button-counter";
import * as TKUnit from "../../TKUnit";
import { isIOS } from "tns-core-modules/platform";
import { isIOS, isAndroid } from "tns-core-modules/platform";
// Integration tests that asser sertain runtime behavior, lifecycle events atc.
@@ -118,4 +118,51 @@ export function test_navigating_away_does_not_excessively_reset() {
// NOTE: Recycling may mess this up so feel free to change the test,
// but ensure a reasonable amount of native setters were called when the views navigate away
assert(1);
}
}
export function test_css_sets_properties() {
const page = helper.navigateToModule("ui/lifecycle/pages/page-two");
const buttons = ["btn1", "btn2", "btn3", "btn4"].map(id => page.getViewById<btnCounter.Button>(id));
buttons.forEach(btn => {
TKUnit.assertEqual(btn.colorSetNativeCount, 1, `Expected ${btn.id}'s native color to propagated exactly once when inflating from xml.`);
TKUnit.assertEqual(btn.colorPropertyChangeCount, 1, `Expected ${btn.id}'s colorChange to be fired exactly once when inflating from xml.`);
});
buttons.forEach(btn => {
btn.className = "";
});
const expectedChangesAfterClearingClasses = [1, 2, 2, 2];
for (var i = 0; i < buttons.length; i++) {
TKUnit.assertEqual(buttons[i].colorSetNativeCount, expectedChangesAfterClearingClasses[i], `Expected ${buttons[i].id} native set after clear.`);
TKUnit.assertEqual(buttons[i].colorPropertyChangeCount, expectedChangesAfterClearingClasses[i], `Expected ${buttons[i].id} change notifications after clear.`);
}
buttons[0].className = "nocolor";
buttons[1].className = "red";
buttons[2].className = "blue";
buttons[3].className = "red blue";
const expectedChangesAfterResettingClasses = [1, 3, 3, 3];
for (let i = 0; i < buttons.length; i++) {
TKUnit.assertEqual(buttons[i].colorSetNativeCount, expectedChangesAfterResettingClasses[i], `Expected ${buttons[i].id} native set after classes are reapplied.`);
TKUnit.assertEqual(buttons[i].colorPropertyChangeCount, expectedChangesAfterResettingClasses[i], `Expected ${buttons[i].id} change notifications classes are reapplied.`);
}
const stack: any = page.getViewById("stack");
page.content = null;
for (let i = 0; i < buttons.length; i++) {
TKUnit.assertEqual(buttons[i].colorSetNativeCount, expectedChangesAfterResettingClasses[i], `Expected ${buttons[i].id} native set to not be called when removed from page.`);
TKUnit.assertEqual(buttons[i].colorPropertyChangeCount, expectedChangesAfterResettingClasses[i], `Expected ${buttons[i].id} change notifications for css properties to not occur when removed from page.`);
}
page.content = stack;
// TODO: The check counts here should be the same as the counts before removing from the page.
const expectedNativeSettersAfterReaddedToPage = isAndroid ? [2, 4, 4, 4] : expectedChangesAfterResettingClasses;
for (let i = 0; i < buttons.length; i++) {
TKUnit.assertEqual(buttons[i].colorSetNativeCount, expectedNativeSettersAfterReaddedToPage[i], `Expected ${buttons[i].id} native set to not be called when added to page.`);
TKUnit.assertEqual(buttons[i].colorPropertyChangeCount, expectedChangesAfterResettingClasses[i], `Expected ${buttons[i].id} change notifications for css properties to not occur when added to page.`);
}
}

View File

@@ -5,6 +5,13 @@ export class Button extends button.Button {
nativeBackgroundRedraws = 0;
backgroundInternalSetNativeCount = 0;
fontInternalSetNativeCount = 0;
colorSetNativeCount = 0;
colorPropertyChangeCount = 0;
constructor() {
super();
this.style.on("colorChange", () => this.colorPropertyChangeCount++);
}
[view.backgroundInternalProperty.setNative](value) {
this.backgroundInternalSetNativeCount++;
@@ -18,5 +25,9 @@ export class Button extends button.Button {
this.nativeBackgroundRedraws++;
super._redrawNativeBackground(value);
}
[view.colorProperty.setNative](value) {
this.colorSetNativeCount++;
return super[view.colorProperty.setNative](value);
}
}
Button.prototype.recycleNativeView = "never";

View File

@@ -0,0 +1,15 @@
Button {
color: orange;
}
.red {
color: red;
}
.blue {
color: blue;
}
.nocolor {
background: red;
}

View File

@@ -0,0 +1,8 @@
<Page xmlns:btnCount="ui/lifecycle/pages/button-counter">
<StackLayout id="stack">
<btnCount:Button id="btn1" text="one" class="nocolor" />
<btnCount:Button id="btn2" text="two" class="red" />
<btnCount:Button id="btn3" text="three" class="blue" />
<btnCount:Button id="btn4" text="four" class="red blue" />
</StackLayout>
</Page>

View File

@@ -5,12 +5,10 @@ export function getNativeItemsCount(bar: segmentedBarModule.SegmentedBar): numbe
}
export function checkNativeItemsTextColor(bar: segmentedBarModule.SegmentedBar): boolean {
var isValid = true;
var attrs = (<UISegmentedControl>bar.nativeViewProtected).titleTextAttributesForState(UIControlState.Normal);
isValid = bar.color && attrs && attrs.valueForKey(NSForegroundColorAttributeName) === bar.color.ios;
return isValid;
var nativeViewColor = bar.color && attrs && attrs.valueForKey(NSForegroundColorAttributeName);
var barColor = bar.color.ios;
return barColor.isEqual(nativeViewColor);
}
export function setNativeSelectedIndex(bar: segmentedBarModule.SegmentedBar, index: number): void {

View File

@@ -67,6 +67,7 @@ export function test_applies_css_changes_to_application_rules_after_page_load()
helper.buildUIAndRunTest(label1, function (views: Array<viewModule.View>) {
application.addCss(".applicationChangedLabelAfter { color: blue; }");
label1.className = "applicationChangedLabelAfter";
console.log("IsLoaded: " + label1.isLoaded);
helper.assertViewColor(label1, "#0000FF");
});
}
@@ -615,7 +616,7 @@ export function test_setInlineStyle_setsLocalValues() {
stack.addChild(testButton);
helper.buildUIAndRunTest(stack, function (views: Array<viewModule.View>) {
(<any>testButton)._applyInlineStyle("color: red;");
(<any>testButton).style = "color: red;";
helper.assertViewColor(testButton, "#FF0000");
});
}
@@ -624,7 +625,7 @@ export function test_setStyle_throws() {
const testButton = new buttonModule.Button();
TKUnit.assertThrows(function () {
(<any>testButton).style = "background-color: red;";
(<any>testButton).style = {};
}, "View.style property is read-only.");
}

View File

@@ -5,6 +5,19 @@ import * as helper from "../helper";
import * as TKUnit from "../../TKUnit";
import { unsetValue } from "tns-core-modules/ui/core/view";
export var test_value_Inherited_after_unset = function () {
let page = helper.getCurrentPage();
page.css = "StackLayout { color: #FF0000; } .blue { color: #0000FF; }";
let btn = new button.Button();
let testStack = new stack.StackLayout();
page.content = testStack;
testStack.addChild(btn);
btn.className = "blue";
helper.assertViewColor(btn, "#0000FF");
btn.className = "";
helper.assertViewColor(btn, "#FF0000");
}
export var test_value_Inherited_stronger_than_Default = function () {
let page = helper.getCurrentPage();
let btn = new button.Button();