From 69ef5ffc491c547ffc49d7d29d9b9393e01bb06f Mon Sep 17 00:00:00 2001 From: Erjan Gavalji Date: Thu, 4 Feb 2016 15:58:38 +0200 Subject: [PATCH 1/8] Apply the fix, suggested by Github userx4080, issue 1371 --- ui/list-view/list-view.android.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/list-view/list-view.android.ts b/ui/list-view/list-view.android.ts index d5ab324bc..9e1af72bc 100644 --- a/ui/list-view/list-view.android.ts +++ b/ui/list-view/list-view.android.ts @@ -151,17 +151,17 @@ export class ListView extends common.ListView { var length = keys.length; var view: viewModule.View; var key; - for (i = 0; i < length; i++) { key = keys[i]; view = this._realizedItems[key]; - - this.notify({ - eventName: ITEMLOADING, - object: this, - index: view[REALIZED_INDEX], - view: view - }); + if (view[REALIZED_INDEX] < this.items.length) { + this.notify({ + eventName: ITEMLOADING, + object: this, + index: view[REALIZED_INDEX], + view: view + }); + } } } } @@ -251,4 +251,4 @@ function ensureListViewAdapterClass() { } ListViewAdapterClass = ListViewAdapter; -} \ No newline at end of file +} From 7a0cda8d67b9e924f7949403cc283ca0f2391a57 Mon Sep 17 00:00:00 2001 From: Vasil Chimev Date: Wed, 10 Feb 2016 11:02:38 +0200 Subject: [PATCH 2/8] Revert dependencies versions --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index d632ed4a2..72a0fa4cf 100644 --- a/package.json +++ b/package.json @@ -38,12 +38,12 @@ }, "typings": "tns-core-modules.d.ts", "dependencies": { - "tns-core-modules-widgets": "1.6.1" + "tns-core-modules-widgets": "1.6.0" }, "nativescript": { "platforms": { - "ios": "1.6.0", - "android": "1.6.0" + "ios": "1.3.0", + "android": "1.3.0" } } } From 4336245aba724808b191c76a2ba69aeaf615f063 Mon Sep 17 00:00:00 2001 From: Rossen Hristov Date: Wed, 10 Feb 2016 11:06:38 +0200 Subject: [PATCH 3/8] Fixed Issue #659. --- ui/frame/frame.ios.ts | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/ui/frame/frame.ios.ts b/ui/frame/frame.ios.ts index 2ab52a4a7..26c494769 100644 --- a/ui/frame/frame.ios.ts +++ b/ui/frame/frame.ios.ts @@ -9,6 +9,7 @@ import uiUtils = require("ui/utils"); import * as types from "utils/types"; import * as animationModule from "ui/animation"; import * as transitionModule from "ui/transition"; +import application = require("application"); global.moduleMerge(frameCommon, exports); @@ -31,6 +32,15 @@ export class Frame extends frameCommon.Frame { constructor() { super(); this._ios = new iOSFrame(this); + + // When there is a 40px high "in-call" status bar, nobody moves the navigationBar top from 20 to 40 and it remains underneath the status bar. + var that = this; + application.ios.addNotificationObserver(UIApplicationDidChangeStatusBarFrameNotification, (notification: NSNotification) => { + that._handleHigherInCallStatusBarIfNeeded(); + if (this._ios.controller.owner.currentPage) { + this._ios.controller.owner.currentPage.requestLayout(); + } + }); } public onLoaded() { @@ -234,6 +244,7 @@ export class Frame extends frameCommon.Frame { public onLayout(left: number, top: number, right: number, bottom: number): void { this._right = right; this._bottom = bottom; + this._handleHigherInCallStatusBarIfNeeded(); this.layoutPage(this.currentPage); if (this._navigateToEntry && this.currentPage) { this.layoutPage(this._navigateToEntry.resolvedPage); @@ -275,6 +286,26 @@ export class Frame extends frameCommon.Frame { window.layoutIfNeeded(); } } + + _handleHigherInCallStatusBarIfNeeded() { + let statusBarHeight = uiUtils.ios.getStatusBarHeight(); + if (!this._ios || + !this._ios.controller || + !this._ios.controller.navigationBar || + this._ios.controller.navigationBar.hidden || + this._ios.controller.navigationBar.frame.origin.y === statusBarHeight) { + return; + } + + trace.write(`Forcing navigationBar.frame.origin.y to ${statusBarHeight} due to a higher in-call status-bar`, trace.categories.Layout); + this._ios.controller.navigationBar.autoresizingMask = UIViewAutoresizing.UIViewAutoresizingNone; + this._ios.controller.navigationBar.removeConstraints((this)._ios.controller.navigationBar.constraints); + this._ios.controller.navigationBar.frame = CGRectMake( + this._ios.controller.navigationBar.frame.origin.x, + statusBarHeight, + this._ios.controller.navigationBar.frame.size.width, + this._ios.controller.navigationBar.frame.size.height); + } } class TransitionDelegate extends NSObject { From 5ad082d7831a11d968308f998ba0be19ca283bc1 Mon Sep 17 00:00:00 2001 From: Rossen Hristov Date: Wed, 10 Feb 2016 14:55:27 +0200 Subject: [PATCH 4/8] Re-factored page navigation transitions. Resolves Issue #811. --- apps/perf-tests/nav-page.ts | 6 ++-- apps/tests/navigation/navigation-tests.ts | 6 ++-- apps/tests/ui/page/page-tests-common.ts | 4 +-- tsconfig.json | 23 ++++++------- ui/frame/frame-common.ts | 33 ++++++++++++------ ui/frame/frame.android.ts | 8 ++--- ui/frame/frame.d.ts | 41 +++++++++++++++++++---- ui/frame/frame.ios.ts | 12 +++---- ui/transition/transition.android.ts | 8 ++--- ui/transition/transition.ios.ts | 13 +++---- 10 files changed, 97 insertions(+), 57 deletions(-) diff --git a/apps/perf-tests/nav-page.ts b/apps/perf-tests/nav-page.ts index 2e4affa51..6d9e8d1a8 100644 --- a/apps/perf-tests/nav-page.ts +++ b/apps/perf-tests/nav-page.ts @@ -171,12 +171,12 @@ export class NavPage extends Page implements definition.ControlsPage { var customTransitionModule = require("./custom-transition"); var customTransition = new customTransitionModule.CustomTransition(duration, curve); navigationTransition = { - transition: customTransition + instance: customTransition }; } else { navigationTransition = { - transition: transitionName, + name: transitionName, duration: duration, curve: curve }; @@ -188,7 +188,7 @@ export class NavPage extends Page implements definition.ControlsPage { backstackVisible: addToBackStackSwitch.checked, clearHistory: clearHistorySwitch.checked, animated: animatedSwitch.checked, - navigationTransition: navigationTransition, + transition: navigationTransition, }); }); stackLayout.addChild(forwardButton); diff --git a/apps/tests/navigation/navigation-tests.ts b/apps/tests/navigation/navigation-tests.ts index fa366b5d0..44c2ec8b7 100644 --- a/apps/tests/navigation/navigation-tests.ts +++ b/apps/tests/navigation/navigation-tests.ts @@ -25,7 +25,7 @@ function _testTransition(navigationTransition: NavigationTransition) { return page; }, animated: true, - navigationTransition: navigationTransition + transition: navigationTransition } helper.navigateWithEntry(navigationEntry); @@ -65,7 +65,7 @@ export var test_Transitions = function () { for (d = 0; d < dlen; d++) { for (c = 0; c < clen; c++) { _testTransition({ - transition: transitions[t], + name: transitions[t], duration: durations[d], curve: curves[c] }); @@ -76,7 +76,7 @@ export var test_Transitions = function () { // Custom transition var customTransitionModule = require("./custom-transition"); var customTransition = new customTransitionModule.CustomTransition(); - _testTransition({transition: customTransition}); + _testTransition({ instance: customTransition }); helper.goBack(); } diff --git a/apps/tests/ui/page/page-tests-common.ts b/apps/tests/ui/page/page-tests-common.ts index 7984c515b..65295efff 100644 --- a/apps/tests/ui/page/page-tests-common.ts +++ b/apps/tests/ui/page/page-tests-common.ts @@ -191,14 +191,14 @@ function _test_PageNavigation_EventSequence(withTransition: boolean) { if (withTransition) { var navigationTransition: FrameModule.NavigationTransition = { - transition: "slide", + name: "slide", duration: 1000, }; var navigationEntry: FrameModule.NavigationEntry = { create: pageFactory, context: context, animated: true, - navigationTransition: navigationTransition + transition: navigationTransition } helper.navigateWithEntry(navigationEntry); } diff --git a/tsconfig.json b/tsconfig.json index 325a0c1e2..b443b95d9 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -53,7 +53,6 @@ "apps/connectivity-demo/app.ts", "apps/connectivity-demo/main-page.ts", "apps/custom-root-view/app.ts", - "apps/custom-root-view/list-view.ts", "apps/cuteness.io/app.ts", "apps/cuteness.io/details-page.ts", "apps/cuteness.io/main-page.ts", @@ -91,16 +90,10 @@ "apps/perf-tests/ApplicationLoadTimeAndFPS/mainPage.ts", "apps/perf-tests/ApplicationSize/app.ts", "apps/perf-tests/ApplicationSize/mainPage.ts", - "apps/perf-tests/common.d.ts", - "apps/perf-tests/common.ts", "apps/perf-tests/ComplexObjectGraphMemoryTest/app.ts", "apps/perf-tests/ComplexObjectGraphMemoryTest/mainPage.ts", "apps/perf-tests/ControlCreationSpeedTest/app.ts", "apps/perf-tests/ControlCreationSpeedTest/mainPage.ts", - "apps/perf-tests/controls-page.d.ts", - "apps/perf-tests/controls-page.ts", - "apps/perf-tests/custom-transition.android.ts", - "apps/perf-tests/custom-transition.ios.ts", "apps/perf-tests/LargeObjectArrayMemoryLeakTest/app.ts", "apps/perf-tests/LargeObjectArrayMemoryLeakTest/mainPage.ts", "apps/perf-tests/LargeObjectArrayMemoryLeakTest/native-calls-wrapper.android.ts", @@ -108,8 +101,6 @@ "apps/perf-tests/LargeObjectArrayMemoryLeakTest/native-calls-wrapper.ios.ts", "apps/perf-tests/LargeObjectArrayMemoryTest/app.ts", "apps/perf-tests/LargeObjectArrayMemoryTest/mainPage.ts", - "apps/perf-tests/nav-page.d.ts", - "apps/perf-tests/nav-page.ts", "apps/perf-tests/NavigationMemoryLeakTest/app.ts", "apps/perf-tests/NavigationMemoryLeakTest/mainPage.ts", "apps/perf-tests/NavigationTest/app.ts", @@ -127,6 +118,14 @@ "apps/perf-tests/SpeedTests/tests-native.ios.ts", "apps/perf-tests/SpeedTests/tests.d.ts", "apps/perf-tests/SpeedTests/tests.ts", + "apps/perf-tests/common.d.ts", + "apps/perf-tests/common.ts", + "apps/perf-tests/controls-page.d.ts", + "apps/perf-tests/controls-page.ts", + "apps/perf-tests/custom-transition.android.ts", + "apps/perf-tests/custom-transition.ios.ts", + "apps/perf-tests/nav-page.d.ts", + "apps/perf-tests/nav-page.ts", "apps/pickers-demo/app.ts", "apps/pickers-demo/main-page.ts", "apps/pickers-demo/model.ts", @@ -149,6 +148,7 @@ "apps/template-settings/view-model.ts", "apps/template-tab-navigation/app.ts", "apps/template-tab-navigation/main-page.ts", + "apps/tests/TKUnit.ts", "apps/tests/app/app.ts", "apps/tests/app/location-example.ts", "apps/tests/app/mainPage.ts", @@ -225,13 +225,12 @@ "apps/tests/testRunner.ts", "apps/tests/text/formatted-string-tests.ts", "apps/tests/timer-tests.ts", - "apps/tests/TKUnit.ts", "apps/tests/trace-tests.ts", "apps/tests/ui-test.ts", + "apps/tests/ui/action-bar/ActionBar_NumberAsText.ts", "apps/tests/ui/action-bar/action-bar-tests-common.ts", "apps/tests/ui/action-bar/action-bar-tests.android.ts", "apps/tests/ui/action-bar/action-bar-tests.ios.ts", - "apps/tests/ui/action-bar/ActionBar_NumberAsText.ts", "apps/tests/ui/activity-indicator/activity-indicator-tests.ts", "apps/tests/ui/animation/animation-tests.ts", "apps/tests/ui/bindable-tests.ts", @@ -707,4 +706,4 @@ "atom": { "rewriteTsconfig": true } -} +} \ No newline at end of file diff --git a/ui/frame/frame-common.ts b/ui/frame/frame-common.ts index fc66b933c..5a63e4421 100644 --- a/ui/frame/frame-common.ts +++ b/ui/frame/frame-common.ts @@ -6,6 +6,7 @@ import * as trace from "trace"; import {resolveFileName} from "file-system/file-name-resolver"; import * as fs from "file-system"; import * as builderModule from "ui/builder"; +import * as platform from "platform"; var builder: typeof builderModule; function ensureBuilder() { @@ -138,11 +139,11 @@ export class Frame extends CustomLayoutView implements definition.Frame { private _backStack: Array; public _currentEntry: definition.BackstackEntry; private _animated: boolean; - private _navigationTransition: definition.NavigationTransition; + private _transition: definition.NavigationTransition; public _isInFrameStack = false; public static defaultAnimatedNavigation = true; - public static defaultNavigationTransition: definition.NavigationTransition; + public static defaultTransition: definition.NavigationTransition; // TODO: Currently our navigation will not be synchronized in case users directly call native navigation methods like Activity.startActivity. @@ -325,12 +326,12 @@ export class Frame extends CustomLayoutView implements definition.Frame { this._animated = value; } - public get navigationTransition(): definition.NavigationTransition { - return this._navigationTransition; + public get transition(): definition.NavigationTransition { + return this._transition; } - public set navigationTransition(value: definition.NavigationTransition) { - this._navigationTransition = value; + public set transition(value: definition.NavigationTransition) { + this._transition = value; } get backStack(): Array { @@ -399,15 +400,25 @@ export class Frame extends CustomLayoutView implements definition.Frame { } public _getNavigationTransition(entry: definition.NavigationEntry): definition.NavigationTransition { - if (entry && isDefined(entry.navigationTransition)) { - return entry.navigationTransition; + if (entry) { + if (platform.device.os === platform.platformNames.ios && isDefined(entry.transitioniOS)) { + return entry.transitioniOS; + } + + if (platform.device.os === platform.platformNames.android && isDefined(entry.transitionAndroid)) { + return entry.transitioniOS; + } + + if (entry && isDefined(entry.transition)) { + return entry.transition; + } } - if (isDefined(this.navigationTransition)) { - return this.navigationTransition; + if (isDefined(this.transition)) { + return this.transition; } - return Frame.defaultNavigationTransition; + return Frame.defaultTransition; } public get navigationBarHeight(): number { diff --git a/ui/frame/frame.android.ts b/ui/frame/frame.android.ts index 2ed763d60..40d482c88 100644 --- a/ui/frame/frame.android.ts +++ b/ui/frame/frame.android.ts @@ -202,11 +202,11 @@ export class Frame extends frameCommon.Frame { frameCommon.Frame.defaultAnimatedNavigation = value; } - public static get defaultNavigationTransition(): definition.NavigationTransition { - return frameCommon.Frame.defaultNavigationTransition; + public static get defaultTransition(): definition.NavigationTransition { + return frameCommon.Frame.defaultTransition; } - public static set defaultNavigationTransition(value: definition.NavigationTransition) { - frameCommon.Frame.defaultNavigationTransition = value; + public static set defaultTransition(value: definition.NavigationTransition) { + frameCommon.Frame.defaultTransition = value; } get containerViewId(): number { diff --git a/ui/frame/frame.d.ts b/ui/frame/frame.d.ts index 177243dbc..e4c8048e9 100644 --- a/ui/frame/frame.d.ts +++ b/ui/frame/frame.d.ts @@ -5,6 +5,7 @@ declare module "ui/frame" { import view = require("ui/core/view"); import observable = require("data/observable"); import pages = require("ui/page"); + import transition = require("ui/transition"); /** * Represents the logical View unit that is responsible for navigation withing an application. @@ -77,7 +78,7 @@ declare module "ui/frame" { /** * Gets or sets the default navigation transition for this frame. */ - navigationTransition: NavigationTransition; + transition: NavigationTransition; /** * Gets or sets if navigation transitions should be animated globally. @@ -87,7 +88,7 @@ declare module "ui/frame" { /** * Gets or sets the default NavigationTransition for all frames across the app. */ - static defaultNavigationTransition: NavigationTransition; + static defaultTransition: NavigationTransition; /** * Gets the AndroidFrame object that represents the Android-specific APIs for this Frame. Valid when running on Android OS. @@ -161,9 +162,19 @@ declare module "ui/frame" { animated?: boolean; /** - * Specifies an optional navigation transition. If not specified, the default platform transition will be used. + * Specifies an optional navigation transition for all platforms. If not specified, the default platform transition will be used. */ - navigationTransition?: NavigationTransition; + transition?: NavigationTransition; + + /** + * Specifies an optional navigation transition for iOS. If not specified, the default platform transition will be used. + */ + transitioniOS?: NavigationTransition; + + /** + * Specifies an optional navigation transition for iOS. If not specified, the default platform transition will be used. + */ + transitionAndroid?: NavigationTransition; /** * True to record the navigation in the backstack, false otherwise. @@ -182,10 +193,28 @@ declare module "ui/frame" { */ export interface NavigationTransition { /** - * Either a string specifying one of the built-in transitions or an user-defined instance of the "ui/transition".Transition class. + * Can be one of the built-in transitions: + * - curl (same as curlUp) (iOS only) + * - curlUp (iOS only) + * - curlDown (iOS only) + * - explode (Android Lollipop an up only) + * - fade + * - flip (same as flipRight) + * - flipRight + * - flipLeft + * - slide (same as slideLeft) + * - slideLeft + * - slideRight + * - slideTop + * - slideBottom */ - transition: any; + name?: string; + /** + * An user-defined instance of the "ui/transition".Transition class. + */ + instance?: transition.Transition; + /** * The length of the transition in milliseconds. If you do not specify this, the default platform transition duration will be used. */ diff --git a/ui/frame/frame.ios.ts b/ui/frame/frame.ios.ts index 26c494769..d3ba2340a 100644 --- a/ui/frame/frame.ios.ts +++ b/ui/frame/frame.ios.ts @@ -189,11 +189,11 @@ export class Frame extends frameCommon.Frame { frameCommon.Frame.defaultAnimatedNavigation = value; } - public static get defaultNavigationTransition(): definition.NavigationTransition { - return frameCommon.Frame.defaultNavigationTransition; + public static get defaultTransition(): definition.NavigationTransition { + return frameCommon.Frame.defaultTransition; } - public static set defaultNavigationTransition(value: definition.NavigationTransition) { - frameCommon.Frame.defaultNavigationTransition = value; + public static set defaultTransition(value: definition.NavigationTransition) { + frameCommon.Frame.defaultTransition = value; } public requestLayout(): void { @@ -640,8 +640,8 @@ function _getTransitionId(nativeTransition: UIViewAnimationTransition, transitio } function _getNativeTransition(navigationTransition: definition.NavigationTransition, push: boolean): UIViewAnimationTransition { - if (types.isString(navigationTransition.transition)) { - switch (navigationTransition.transition.toLowerCase()) { + if (navigationTransition.name) { + switch (navigationTransition.name.toLowerCase()) { case "flip": case "flipright": return push ? UIViewAnimationTransition.UIViewAnimationTransitionFlipFromRight : UIViewAnimationTransition.UIViewAnimationTransitionFlipFromLeft; diff --git a/ui/transition/transition.android.ts b/ui/transition/transition.android.ts index 3eeed0e78..e9d7f589c 100644 --- a/ui/transition/transition.android.ts +++ b/ui/transition/transition.android.ts @@ -47,8 +47,8 @@ export function _clearForwardTransitions(fragment: any): void { export function _setAndroidFragmentTransitions(navigationTransition: frameModule.NavigationTransition, currentFragment: any, newFragment: any, fragmentTransaction: any): void { var name; - if (types.isString(navigationTransition.transition)) { - name = navigationTransition.transition.toLowerCase(); + if (navigationTransition.name) { + name = navigationTransition.name.toLowerCase(); } var useLollipopTransition = name && (name.indexOf("slide") === 0 || name === "fade" || name === "explode") && _sdkVersion >= 21; @@ -153,7 +153,7 @@ export function _setAndroidFragmentTransitions(navigationTransition: frameModule return; } - var transition: Transition; + var transition: definition.Transition; if (name) { if (name.indexOf("slide") === 0) { var slideTransitionModule = require("./slide-transition"); @@ -171,7 +171,7 @@ export function _setAndroidFragmentTransitions(navigationTransition: frameModule } } else { - transition = navigationTransition.transition; // User-defined instance of Transition + transition = navigationTransition.instance; // User-defined instance of Transition } if (transition) { diff --git a/ui/transition/transition.ios.ts b/ui/transition/transition.ios.ts index 417e6e4df..24b7d5909 100644 --- a/ui/transition/transition.ios.ts +++ b/ui/transition/transition.ios.ts @@ -6,13 +6,13 @@ import trace = require("trace"); class AnimatedTransitioning extends NSObject implements UIViewControllerAnimatedTransitioning { public static ObjCProtocols = [UIViewControllerAnimatedTransitioning]; - private _transition: Transition; + private _transition: definition.Transition; private _operation: UINavigationControllerOperation; private _fromVC: UIViewController; private _toVC: UIViewController; private _transitionType: string; - public static init(transition: Transition, operation: UINavigationControllerOperation, fromVC: UIViewController, toVC: UIViewController): AnimatedTransitioning { + public static init(transition: definition.Transition, operation: UINavigationControllerOperation, fromVC: UIViewController, toVC: UIViewController): AnimatedTransitioning { var impl = AnimatedTransitioning.new(); impl._transition = transition; impl._operation = operation; @@ -31,6 +31,7 @@ class AnimatedTransitioning extends NSObject implements UIViewControllerAnimated case UINavigationControllerOperation.UINavigationControllerOperationPop: this._transitionType = "pop"; break; case UINavigationControllerOperation.UINavigationControllerOperationNone: this._transitionType = "none"; break; } + trace.write(`START ${this._transition} ${this._transitionType}`, trace.categories.Transition); this._transition.animateIOSTransition(containerView, this._fromVC.view, this._toVC.view, this._operation, completion); } @@ -87,10 +88,10 @@ export class Transition implements definition.Transition { } export function _createIOSAnimatedTransitioning(navigationTransition: frame.NavigationTransition, operation: UINavigationControllerOperation, fromVC: UIViewController, toVC: UIViewController): UIViewControllerAnimatedTransitioning { - var transition: Transition; + var transition: definition.Transition; - if (types.isString(navigationTransition.transition)) { - var name = navigationTransition.transition.toLowerCase(); + if (navigationTransition.name) { + var name = navigationTransition.name.toLowerCase(); if (name.indexOf("slide") === 0) { var slideTransitionModule = require("./slide-transition"); var direction = name.substr("slide".length) || "left"; //Extract the direction from the string @@ -102,7 +103,7 @@ export function _createIOSAnimatedTransitioning(navigationTransition: frame.Navi } } else { - transition = navigationTransition.transition; + transition = navigationTransition.instance; } if (transition) { From 721e5df58bdf7f7b87d86130b466b61b53adb49d Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Tue, 9 Feb 2016 17:31:50 +0200 Subject: [PATCH 5/8] grid-layout layout rounding fixes added tests --- apps/tests/layouts/grid-layout-tests.ts | 25 +++ ui/layouts/grid-layout/grid-layout.ios.ts | 234 ++++++++++------------ 2 files changed, 127 insertions(+), 132 deletions(-) diff --git a/apps/tests/layouts/grid-layout-tests.ts b/apps/tests/layouts/grid-layout-tests.ts index fb36eba8b..9a263107b 100644 --- a/apps/tests/layouts/grid-layout-tests.ts +++ b/apps/tests/layouts/grid-layout-tests.ts @@ -687,6 +687,31 @@ export class GridLayoutTest extends testModule.UITest { TKUnit.assertTrue(rows[0].isStar, "First row should be *"); TKUnit.assertTrue(rows[1].isAbsolute, "Second row should be Absolute"); } + + public test_columns_widths() { + this.testView.width = layoutHelper.dp(300); + this.testView.height = layoutHelper.dp(500); + + this.testView.addColumn(new ItemSpec(1, GridUnitType.star)); + this.testView.addColumn(new ItemSpec(layoutHelper.dp(100), GridUnitType.pixel)); + this.testView.addColumn(new ItemSpec(2, GridUnitType.star)); + + this.testView.addRow(new ItemSpec(1, GridUnitType.star)); + this.testView.addRow(new ItemSpec(layoutHelper.dp(100), GridUnitType.pixel)); + this.testView.addRow(new ItemSpec(2, GridUnitType.star)); + + this.waitUntilTestElementLayoutIsValid(); + + var cols = this.testView.getColumns(); + TKUnit.assertAreClose(cols[0].actualLength, layoutHelper.dp(67), DELTA, "Column[0] actual length should be 67"); + TKUnit.assertAreClose(cols[1].actualLength, layoutHelper.dp(100), DELTA, "Column[1] actual length should be 100"); + TKUnit.assertAreClose(cols[2].actualLength, layoutHelper.dp(133), DELTA, "Column[2] actual length should be 133"); + + var rows = this.testView.getRows(); + TKUnit.assertAreClose(rows[0].actualLength, layoutHelper.dp(133), DELTA, "Row[0] actual length should be 133"); + TKUnit.assertAreClose(rows[1].actualLength, layoutHelper.dp(100), DELTA, "Row[1] actual length should be 100"); + TKUnit.assertAreClose(rows[2].actualLength, layoutHelper.dp(267), DELTA, "Row[2] actual length should be 267"); + } } export function createTestCase(): GridLayoutTest { diff --git a/ui/layouts/grid-layout/grid-layout.ios.ts b/ui/layouts/grid-layout/grid-layout.ios.ts index 61ba6cc1a..c10354487 100644 --- a/ui/layouts/grid-layout/grid-layout.ios.ts +++ b/ui/layouts/grid-layout/grid-layout.ios.ts @@ -368,12 +368,15 @@ class MeasureHelper { infinityWidth: boolean = false; infinityHeight: boolean = false; + private minColumnStarValue: number = 0; + private maxColumnStarValue: number = 0; + + private minRowStarValue: number = 0; + private maxRowStarValue: number = 0; + measuredWidth: number = 0; measuredHeight: number = 0; - private columnStarValue: number; - private rowStarValue: number; - private fakeRowAdded: boolean = false; private fakeColumnAdded: boolean = false; @@ -388,10 +391,6 @@ class MeasureHelper { this.singleColumnGroup = new ItemGroup(this.singleColumn); } - public getColumnsFixed(): boolean { - return this.columnStarValue >= 0; - } - public setInfinityWidth(value: boolean): void { if (this.infinityWidth !== value) { this.infinityWidth = value; @@ -513,8 +512,10 @@ class MeasureHelper { MeasureHelper.initList(this.rows); MeasureHelper.initList(this.columns); - this.columnStarValue = -1; - this.rowStarValue = -1; + this.minColumnStarValue = -1; + this.minRowStarValue = -1; + this.maxColumnStarValue = -1; + this.maxRowStarValue = -1; } private itemMeasured(measureSpec: MeasureSpecs, isFakeMeasure: boolean): void { @@ -552,24 +553,19 @@ class MeasureHelper { let columnCount = this.columns.length; for (let i = 0; i < columnCount; i++) { let item: ItemGroup = this.columns[i]; - - // Star columns are still zeros (not calculated). - currentColumnWidth += item.length; if (item.rowOrColumn.isStar) { columnStarCount += item.rowOrColumn.value; } - } - - this.columnStarValue = columnStarCount > 0 ? (this.width - currentColumnWidth) / columnStarCount : 0; - - if (this.stretchedHorizontally) { - for (let i = 0; i < columnCount; i++) { - let item: ItemGroup = this.columns[i]; - if (item.getIsStar()) { - item.length = item.rowOrColumn.value * this.columnStarValue; - } + else { + // Star columns are still zeros (not calculated). + currentColumnWidth += item.length; } } + + let widthForStarColumns = Math.max(0, this.width - currentColumnWidth); + this.maxColumnStarValue = columnStarCount > 0 ? widthForStarColumns / columnStarCount : 0; + + MeasureHelper.updateStarLength(this.columns, this.maxColumnStarValue); } private fixRows(): void { @@ -579,22 +575,33 @@ class MeasureHelper { let rowCount = this.rows.length; for (let i = 0; i < rowCount; i++) { let item: ItemGroup = this.rows[i]; - - // Star rows are still zeros (not calculated). - currentRowHeight += item.length; if (item.rowOrColumn.isStar) { rowStarCount += item.rowOrColumn.value; } + else { + // Star rows are still zeros (not calculated). + currentRowHeight += item.length; + } } - this.rowStarValue = rowStarCount > 0 ? (this.height - currentRowHeight) / rowStarCount : 0; + let heightForStarRows = Math.max(0, this.height - currentRowHeight); + this.maxRowStarValue = rowStarCount > 0 ? heightForStarRows / rowStarCount : 0; - if (this.stretchedVertically) { - for (let i = 0; i < rowCount; i++) { - let item: ItemGroup = this.rows[i]; - if (item.getIsStar()) { - item.length = item.rowOrColumn.value * this.rowStarValue; - } + MeasureHelper.updateStarLength(this.rows, this.maxRowStarValue); + } + + private static updateStarLength(list: Array, starValue: number): void { + let offset = 0; + let roundedOffset = 0; + for (let i = 0, rowCount = list.length; i < rowCount; i++) { + let item = list[i]; + if (item.getIsStar()) { + offset += item.rowOrColumn.value * starValue; + + let actualLength = offset - roundedOffset; + let roundedLength = Math.round(actualLength); + item.length = roundedLength; + roundedOffset += roundedLength; } } } @@ -740,6 +747,18 @@ class MeasureHelper { } } + // If we are not stretched and minColumnStarValue is less than maxColumnStarValue + // we need to reduce the width of star columns. + if (!this.stretchedHorizontally && this.minColumnStarValue != -1 && this.minColumnStarValue < this.maxColumnStarValue) { + MeasureHelper.updateStarLength(this.columns, this.minColumnStarValue); + } + + // If we are not stretched and minRowStarValue is less than maxRowStarValue + // we need to reduce the height of star maxRowStarValue. + if (!this.stretchedVertically && this.minRowStarValue != -1 && this.minRowStarValue < this.maxRowStarValue) { + MeasureHelper.updateStarLength(this.rows, this.minRowStarValue); + } + this.measuredWidth = MeasureHelper.getMeasureLength(this.columns); this.measuredHeight = MeasureHelper.getMeasureLength(this.rows); } @@ -802,18 +821,14 @@ class MeasureHelper { let rowIndex = measureSpec.getRowIndex(); let rowSpanEnd = rowIndex + measureSpec.getRowSpan(); - let columnsWidth = 0; + let measureWidth = 0; let growSize = 0; for (let i = columnIndex; i < columnSpanEnd; i++) { let columnGroup: ItemGroup = this.columns[i]; - if (!columnGroup.getIsStar()) { - columnsWidth += columnGroup.length; - } + measureWidth += columnGroup.length; } - let measureWidth = Math.floor(columnsWidth + measureSpec.starColumnsCount * this.columnStarValue); - let widthMeasureSpec = utils.layout.makeMeasureSpec(measureWidth, this.stretchedHorizontally ? utils.layout.EXACTLY : utils.layout.AT_MOST); let heightMeasureSpec = (measureSpec.autoRowsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelHeight, utils.layout.EXACTLY); @@ -821,24 +836,7 @@ class MeasureHelper { let childMeasuredWidth = childSize.measuredWidth; let childMeasuredHeight = childSize.measuredHeight; - // Distribute width over star columns - if (!this.stretchedHorizontally) { - let remainingSpace = childMeasuredWidth; - for (let i = columnIndex; i < columnSpanEnd; i++) { - let columnGroup: ItemGroup = this.columns[i]; - remainingSpace -= columnGroup.length; - } - - if (remainingSpace > 0) { - growSize = remainingSpace / measureSpec.starColumnsCount; - for (let i = columnIndex; i < columnSpanEnd; i++) { - let columnGroup: ItemGroup = this.columns[i]; - if (columnGroup.getIsStar()) { - columnGroup.length += growSize; - } - } - } - } + this.updateMinColumnStarValueIfNeeded(measureSpec, childMeasuredWidth); // Distribute height over auto rows if (measureSpec.autoRowsCount > 0) { @@ -868,17 +866,13 @@ class MeasureHelper { let columnSpanEnd = columnIndex + measureSpec.getColumnSpan(); let rowIndex = measureSpec.getRowIndex(); let rowSpanEnd = rowIndex + measureSpec.getRowSpan(); - let rowsHeight = 0; + let measureHeight = 0; for (let i = rowIndex; i < rowSpanEnd; i++) { let rowGroup: ItemGroup = this.rows[i]; - if (!rowGroup.getIsStar()) { - rowsHeight += rowGroup.length; - } + measureHeight += rowGroup.length; } - let measureHeight = Math.floor(rowsHeight + measureSpec.starRowsCount * this.rowStarValue); - let widthMeasureSpec = (measureSpec.autoColumnsCount > 0) ? this.infinity : utils.layout.makeMeasureSpec(measureSpec.pixelWidth, utils.layout.EXACTLY); let heightMeasureSpec = utils.layout.makeMeasureSpec(measureHeight, this.stretchedVertically ? utils.layout.EXACTLY : utils.layout.AT_MOST); @@ -910,25 +904,7 @@ class MeasureHelper { } } - // Distribute height over star rows - if (!this.stretchedVertically) { - remainingSpace = childMeasuredHeight; - for (let i = rowIndex; i < rowSpanEnd; i++) { - let rowGroup: ItemGroup = this.rows[i]; - remainingSpace -= rowGroup.length; - } - - if (remainingSpace > 0) { - growSize = remainingSpace / measureSpec.starRowsCount; - for (let i = rowIndex; i < rowSpanEnd; i++) { - let rowGroup: ItemGroup = this.rows[i]; - if (rowGroup.getIsStar()) { - rowGroup.length += growSize; - } - } - } - } - + this.updateMinRowStarValueIfNeeded(measureSpec, childMeasuredHeight); this.itemMeasured(measureSpec, false); } @@ -938,25 +914,18 @@ class MeasureHelper { let rowIndex = measureSpec.getRowIndex(); let rowSpanEnd = rowIndex + measureSpec.getRowSpan(); - let columnsWidth = 0; + let measureWidth = 0; for (let i = columnIndex; i < columnSpanEnd; i++) { let columnGroup: ItemGroup = this.columns[i]; - if (!columnGroup.getIsStar()) { - columnsWidth += columnGroup.length; - } + measureWidth += columnGroup.length; } - let rowsHeight = 0; + let measureHeight = 0; for (let i = rowIndex; i < rowSpanEnd; i++) { let rowGroup: ItemGroup = this.rows[i]; - if (!rowGroup.getIsStar()) { - rowsHeight += rowGroup.length; - } + measureHeight += rowGroup.length; } - let measureWidth = Math.floor(columnsWidth + measureSpec.starColumnsCount * this.columnStarValue); - let measureHeight = Math.floor(rowsHeight + measureSpec.starRowsCount * this.rowStarValue); - // if (have stars) & (not stretch) - at most let widthMeasureSpec = utils.layout.makeMeasureSpec(measureWidth, (measureSpec.starColumnsCount > 0 && !this.stretchedHorizontally) ? utils.layout.AT_MOST : utils.layout.EXACTLY); @@ -968,45 +937,46 @@ class MeasureHelper { let childMeasuredWidth = childSize.measuredWidth; let childMeasuredHeight = childSize.measuredHeight; - let remainingSpace = childMeasuredWidth; - let growSize = 0; - - if (!this.stretchedHorizontally) { - for (let i = columnIndex; i < columnSpanEnd; i++) { - let columnGroup: ItemGroup = this.columns[i]; - remainingSpace -= columnGroup.length; - } - - if (remainingSpace > 0) { - growSize = remainingSpace / measureSpec.starColumnsCount; - for (let i = columnIndex; i < columnSpanEnd; i++) { - let columnGroup: ItemGroup = this.columns[i]; - if (columnGroup.getIsStar()) { - columnGroup.length += growSize; - } - } - } - } - - remainingSpace = childMeasuredHeight; - - if (!this.stretchedVertically) { - for (let i = rowIndex; i < rowSpanEnd; i++) { - let rowGroup: ItemGroup = this.rows[i]; - remainingSpace -= rowGroup.length; - } - - if (remainingSpace > 0) { - growSize = remainingSpace / measureSpec.starRowsCount; - for (let i = rowIndex; i < rowSpanEnd; i++) { - let rowGroup: ItemGroup = this.rows[i]; - if (rowGroup.getIsStar()) { - rowGroup.length += growSize; - } - } - } - } - + this.updateMinColumnStarValueIfNeeded(measureSpec, childMeasuredWidth); + this.updateMinRowStarValueIfNeeded(measureSpec, childMeasuredHeight); this.itemMeasured(measureSpec, false); } -} + + private updateMinRowStarValueIfNeeded(measureSpec: MeasureSpecs, childMeasuredHeight: number): void { + if (!this.stretchedVertically && measureSpec.starRowsCount > 0) { + let remainingSpace = childMeasuredHeight; + let rowIndex = measureSpec.getRowIndex(); + let rowSpanEnd = rowIndex + measureSpec.getRowSpan(); + for (let i = rowIndex; i < rowSpanEnd; i++) { + let rowGroup = this.rows[i]; + if (!rowGroup.getIsStar()) { + remainingSpace -= rowGroup.length; + } + } + + if (remainingSpace > 0) { + this.minRowStarValue = Math.max(remainingSpace / measureSpec.starRowsCount, this.minRowStarValue); + } + } + } + + private updateMinColumnStarValueIfNeeded(measureSpec: MeasureSpecs, childMeasuredWidth: number): void { + // When not stretched star columns are not fixed so we may grow them here + // if there is an element that spans on multiple columns + if (!this.stretchedHorizontally && measureSpec.starColumnsCount > 0) { + let remainingSpace = childMeasuredWidth; + let columnIndex = measureSpec.getColumnIndex(); + let columnSpanEnd = columnIndex + measureSpec.getColumnSpan(); + for (let i = columnIndex; i < columnSpanEnd; i++) { + let columnGroup = this.columns[i]; + if (!columnGroup.getIsStar()) { + remainingSpace -= columnGroup.length; + } + } + + if (remainingSpace > 0) { + this.minColumnStarValue = Math.max(remainingSpace / measureSpec.starColumnsCount, this.minColumnStarValue); + } + } + } +} \ No newline at end of file From 6f93030b5d13f8d55cacfbf2ad3c1db63a4f6492 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Wed, 10 Feb 2016 16:17:33 +0200 Subject: [PATCH 6/8] grid-layout distribute remaining space over stars but preserve their aspect. ts lint errors fixed android scroll-view tests fixed for different device density added grid-layout test --- apps/tests/layouts/grid-layout-tests.ts | 33 ++-- .../tests/ui/scroll-view/scroll-view-tests.ts | 161 ++++-------------- ui/layouts/grid-layout/grid-layout.ios.ts | 4 +- 3 files changed, 53 insertions(+), 145 deletions(-) diff --git a/apps/tests/layouts/grid-layout-tests.ts b/apps/tests/layouts/grid-layout-tests.ts index 9a263107b..7b2bc7995 100644 --- a/apps/tests/layouts/grid-layout-tests.ts +++ b/apps/tests/layouts/grid-layout-tests.ts @@ -689,25 +689,36 @@ export class GridLayoutTest extends testModule.UITest { } public test_columns_widths() { - this.testView.width = layoutHelper.dp(300); - this.testView.height = layoutHelper.dp(500); + this.testView.width = layoutHelper.dp(400); + this.testView.height = layoutHelper.dp(600); - this.testView.addColumn(new ItemSpec(1, GridUnitType.star)); - this.testView.addColumn(new ItemSpec(layoutHelper.dp(100), GridUnitType.pixel)); - this.testView.addColumn(new ItemSpec(2, GridUnitType.star)); - - this.testView.addRow(new ItemSpec(1, GridUnitType.star)); - this.testView.addRow(new ItemSpec(layoutHelper.dp(100), GridUnitType.pixel)); - this.testView.addRow(new ItemSpec(2, GridUnitType.star)); + let grid = new GridLayout(); + this.testView.addChild(grid); + grid.horizontalAlignment = enums.HorizontalAlignment.left; + grid.verticalAlignment = enums.VerticalAlignment.top; + + grid.addColumn(new ItemSpec(1, GridUnitType.star)); + grid.addColumn(new ItemSpec(layoutHelper.dp(100), GridUnitType.pixel)); + grid.addColumn(new ItemSpec(2, GridUnitType.star)); + + grid.addRow(new ItemSpec(1, GridUnitType.star)); + grid.addRow(new ItemSpec(layoutHelper.dp(100), GridUnitType.pixel)); + grid.addRow(new ItemSpec(2, GridUnitType.star)); + let btn = new Button(); + btn.width = layoutHelper.dp(300); + btn.height = layoutHelper.dp(500); + grid.addChild(btn); + GridLayout.setColumnSpan(btn, 3); + GridLayout.setRowSpan(btn, 3); this.waitUntilTestElementLayoutIsValid(); - var cols = this.testView.getColumns(); + var cols = grid.getColumns(); TKUnit.assertAreClose(cols[0].actualLength, layoutHelper.dp(67), DELTA, "Column[0] actual length should be 67"); TKUnit.assertAreClose(cols[1].actualLength, layoutHelper.dp(100), DELTA, "Column[1] actual length should be 100"); TKUnit.assertAreClose(cols[2].actualLength, layoutHelper.dp(133), DELTA, "Column[2] actual length should be 133"); - var rows = this.testView.getRows(); + var rows = grid.getRows(); TKUnit.assertAreClose(rows[0].actualLength, layoutHelper.dp(133), DELTA, "Row[0] actual length should be 133"); TKUnit.assertAreClose(rows[1].actualLength, layoutHelper.dp(100), DELTA, "Row[1] actual length should be 100"); TKUnit.assertAreClose(rows[2].actualLength, layoutHelper.dp(267), DELTA, "Row[2] actual length should be 267"); diff --git a/apps/tests/ui/scroll-view/scroll-view-tests.ts b/apps/tests/ui/scroll-view/scroll-view-tests.ts index 8ff74fbfd..3eba7778e 100644 --- a/apps/tests/ui/scroll-view/scroll-view-tests.ts +++ b/apps/tests/ui/scroll-view/scroll-view-tests.ts @@ -27,8 +27,21 @@ import scrollViewModule = require("ui/scroll-view"); //  class ScrollLayoutTest extends testModule.UITest { + public create(): scrollViewModule.ScrollView { - return new scrollViewModule.ScrollView(); + let scrollView = new scrollViewModule.ScrollView(); + scrollView.orientation = enums.Orientation.vertical; + + scrollView.width = layoutHelper.dp(200); + scrollView.height = layoutHelper.dp(300); + + let btn = new button.Button(); + btn.text = "test"; + btn.width = layoutHelper.dp(500); + btn.height = layoutHelper.dp(500); + scrollView.content = btn; + + return scrollView; } public test_snippets() { @@ -69,78 +82,38 @@ class ScrollLayoutTest extends testModule.UITest { } public test_scrollabeHeight_vertical_orientation_when_content_is_small() { - this.testView.orientation = enums.Orientation.vertical; - this.testView.width = 200; - this.testView.height = 300; - - let btn = new button.Button(); - btn.text = "test"; - btn.height = 100; - this.testView.content = btn; - + this.testView.content.height = 100; this.waitUntilTestElementLayoutIsValid(); + TKUnit.assertEqual(this.testView.scrollableHeight, 0, "this.testView.scrollableHeight"); TKUnit.assertEqual(this.testView.scrollableWidth, 0, "this.testView.scrollableWidth"); } public test_scrollabeHeight_vertical_orientation_when_content_is_big() { - this.testView.orientation = enums.Orientation.vertical; - - this.testView.width = 200; - this.testView.height = 300; - - let btn = new button.Button(); - btn.text = "test"; - btn.height = 500; - this.testView.content = btn; - this.waitUntilTestElementLayoutIsValid(); - TKUnit.assertAreClose(this.testView.scrollableHeight, 200, 0.4, "this.testView.scrollableHeight"); - TKUnit.assertEqual(this.testView.scrollableWidth, 0, "this.testView.scrollableWidth"); + TKUnit.assertAreClose(layoutHelper.dip(this.testView.scrollableHeight), 200, 0.4, "this.testView.scrollableHeight"); + TKUnit.assertEqual(this.testView.scrollableWidth, 0, "this.testView.scrollableWidth"); } public test_scrollabeWidth_horizontal_orientation_when_content_is_small() { - this.testView.orientation = enums.Orientation.vertical; - this.testView.width = 200; - this.testView.height = 300; - - let btn = new button.Button(); - btn.text = "test"; - btn.width = 100; - this.testView.content = btn; - + this.testView.orientation = enums.Orientation.horizontal; + this.testView.content.width = 100; this.waitUntilTestElementLayoutIsValid(); + TKUnit.assertEqual(this.testView.scrollableHeight, 0, "this.testView.scrollableHeight"); TKUnit.assertEqual(this.testView.scrollableWidth, 0, "this.testView.scrollableWidth"); } public test_scrollabeWidth_horizontal_orientation_when_content_is_big() { this.testView.orientation = enums.Orientation.horizontal; - - this.testView.width = 200; - this.testView.height = 300; - - let btn = new button.Button(); - btn.text = "test"; - btn.width = 500; - this.testView.content = btn; - this.waitUntilTestElementLayoutIsValid(); + TKUnit.assertEqual(this.testView.scrollableHeight, 0, "this.testView.scrollableHeight"); - TKUnit.assertAreClose(this.testView.scrollableWidth, 300, 0.4, "this.testView.scrollableWidth"); + TKUnit.assertAreClose(layoutHelper.dip(this.testView.scrollableWidth), 300, 0.4, "this.testView.scrollableWidth"); } public test_scrollToVerticalOffset_no_animation() { - this.testView.orientation = enums.Orientation.vertical; - - this.testView.width = 200; - this.testView.height = 300; - - let btn = new button.Button(); - btn.text = "test"; - btn.height = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); TKUnit.assertEqual(this.testView.verticalOffset, 0, "this.testView.verticalOffset"); @@ -149,15 +122,6 @@ class ScrollLayoutTest extends testModule.UITest { } public test_scrollToVerticalOffset_with_animation() { - this.testView.orientation = enums.Orientation.vertical; - - this.testView.width = 200; - this.testView.height = 300; - - let btn = new button.Button(); - btn.text = "test"; - btn.height = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); TKUnit.assertEqual(this.testView.verticalOffset, 0, "this.testView.verticalOffset"); @@ -174,14 +138,6 @@ class ScrollLayoutTest extends testModule.UITest { public test_scrollToHorizontalOffset_no_animation() { this.testView.orientation = enums.Orientation.horizontal; - - this.testView.width = 200; - this.testView.height = 300; - - let btn = new button.Button(); - btn.text = "test"; - btn.width = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); TKUnit.assertEqual(this.testView.horizontalOffset, 0, "this.testView.horizontalOffset"); @@ -191,14 +147,6 @@ class ScrollLayoutTest extends testModule.UITest { public test_scrollToHorizontalOffset_with_animation() { this.testView.orientation = enums.Orientation.horizontal; - - this.testView.width = 200; - this.testView.height = 300; - - let btn = new button.Button(); - btn.text = "test"; - btn.width = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); TKUnit.assertEqual(this.testView.horizontalOffset, 0, "this.testView.horizontalOffset"); @@ -214,19 +162,9 @@ class ScrollLayoutTest extends testModule.UITest { } public test_scrollView_persistsState_vertical() { - this.testView.orientation = enums.Orientation.vertical; - - this.testView.width = 200; - this.testView.height = 300; - - var btn = new button.Button(); - btn.text = "test"; - btn.height = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); this.testView.scrollToVerticalOffset(layoutHelper.dp(100), false); - TKUnit.assertAreClose(layoutHelper.dip(this.testView.verticalOffset), 100, 0.1, "this.testView.verticalOffset before navigation"); helper.do_PageTest_WithButton((t) => { @@ -242,14 +180,6 @@ class ScrollLayoutTest extends testModule.UITest { public test_scrollView_persistsState_horizontal() { this.testView.orientation = enums.Orientation.horizontal; - - this.testView.width = 200; - this.testView.height = 300; - - var btn = new button.Button(); - btn.text = "test"; - btn.width = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); this.testView.scrollToHorizontalOffset(layoutHelper.dp(100), false); @@ -268,23 +198,14 @@ class ScrollLayoutTest extends testModule.UITest { } public test_scrollView_vertical_raised_scroll_event() { - this.testView.orientation = enums.Orientation.vertical; - var scrollY: number; this.testView.on(scrollViewModule.ScrollView.scrollEvent, (args: scrollViewModule.ScrollEventData) => { scrollY = args.scrollY; }); - this.testView.width = 200; - this.testView.height = 300; - - var btn = new button.Button(); - btn.text = "test"; - btn.height = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); - this.testView.scrollToVerticalOffset(100, false); + this.testView.scrollToVerticalOffset(layoutHelper.dp(100), false); TKUnit.waitUntilReady(function () { return scrollY > 0; }); TKUnit.assertEqual(scrollY, this.testView.verticalOffset); } @@ -297,23 +218,14 @@ class ScrollLayoutTest extends testModule.UITest { scrollX = args.scrollX; }); - this.testView.width = 200; - this.testView.height = 300; - - var btn = new button.Button(); - btn.text = "test"; - btn.width = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); - this.testView.scrollToHorizontalOffset(100, false); + this.testView.scrollToHorizontalOffset(layoutHelper.dp(100), false); TKUnit.waitUntilReady(function () { return scrollX > 0; }); TKUnit.assertEqual(scrollX, this.testView.horizontalOffset); } public test_scrollView_vertical_raised_scroll_event_after_loaded() { - this.testView.orientation = enums.Orientation.vertical; - this.waitUntilTestElementIsLoaded(); var scrollY: number; @@ -321,23 +233,14 @@ class ScrollLayoutTest extends testModule.UITest { scrollY = args.scrollY; }); - this.testView.width = 200; - this.testView.height = 300; - - var btn = new button.Button(); - btn.text = "test"; - btn.height = 500; - this.testView.content = btn; - this.waitUntilTestElementLayoutIsValid(); - - this.testView.scrollToVerticalOffset(100, false); + this.testView.scrollToVerticalOffset(layoutHelper.dp(100), false); TKUnit.waitUntilReady(function () { return scrollY > 0; }); TKUnit.assertEqual(scrollY, this.testView.verticalOffset); + TKUnit.assertEqual(scrollY, layoutHelper.dp(100)); } public test_scrollView_horizontal_raised_scroll_event_after_loaded() { this.testView.orientation = enums.Orientation.horizontal; - this.waitUntilTestElementIsLoaded(); var scrollX: number; @@ -345,18 +248,12 @@ class ScrollLayoutTest extends testModule.UITest { scrollX = args.scrollX; }); - this.testView.width = 200; - this.testView.height = 300; - - var btn = new button.Button(); - btn.text = "test"; - btn.width = 500; - this.testView.content = btn; this.waitUntilTestElementLayoutIsValid(); - this.testView.scrollToHorizontalOffset(100, false); + this.testView.scrollToHorizontalOffset(layoutHelper.dp(100), false); TKUnit.waitUntilReady(function () { return scrollX > 0; }); TKUnit.assertEqual(scrollX, this.testView.horizontalOffset); + TKUnit.assertEqual(scrollX, layoutHelper.dp(100)); } } diff --git a/ui/layouts/grid-layout/grid-layout.ios.ts b/ui/layouts/grid-layout/grid-layout.ios.ts index c10354487..a8d46defc 100644 --- a/ui/layouts/grid-layout/grid-layout.ios.ts +++ b/ui/layouts/grid-layout/grid-layout.ios.ts @@ -749,13 +749,13 @@ class MeasureHelper { // If we are not stretched and minColumnStarValue is less than maxColumnStarValue // we need to reduce the width of star columns. - if (!this.stretchedHorizontally && this.minColumnStarValue != -1 && this.minColumnStarValue < this.maxColumnStarValue) { + if (!this.stretchedHorizontally && this.minColumnStarValue !== -1 && this.minColumnStarValue < this.maxColumnStarValue) { MeasureHelper.updateStarLength(this.columns, this.minColumnStarValue); } // If we are not stretched and minRowStarValue is less than maxRowStarValue // we need to reduce the height of star maxRowStarValue. - if (!this.stretchedVertically && this.minRowStarValue != -1 && this.minRowStarValue < this.maxRowStarValue) { + if (!this.stretchedVertically && this.minRowStarValue !== -1 && this.minRowStarValue < this.maxRowStarValue) { MeasureHelper.updateStarLength(this.rows, this.minRowStarValue); } From 99d4f9ea0cd7927570d998e17611a19666df41b9 Mon Sep 17 00:00:00 2001 From: Yavor Georgiev Date: Wed, 10 Feb 2016 18:19:04 +0200 Subject: [PATCH 7/8] Replace -[NSObject performSelector:] with NSInvocation It appears that `-[NSObject performSelector:]` returns a dummy value when calling a void method on the iOS Simulator, whereas it correctly returns `nil` on a device. Since `-[NSObject performSelector:]` is declared as returning `id`, the iOS runtime tries to marshal the dummy value to a JavaScript object and fails because the dummy value is not a valid Objective-C object. The fix is to use `-[NSObject valueForKey:]` for non-void zero-parameter methods and `NSInvocation` for everything else. --- ui/transition/transition.ios.ts | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ui/transition/transition.ios.ts b/ui/transition/transition.ios.ts index 24b7d5909..3cecea868 100644 --- a/ui/transition/transition.ios.ts +++ b/ui/transition/transition.ios.ts @@ -3,6 +3,18 @@ import frame = require("ui/frame"); import types = require("utils/types"); import trace = require("trace"); +module UIViewControllerAnimatedTransitioningMethods { + let methodSignature = NSMethodSignature.signatureWithObjCTypes("v@:c"); + let invocation = NSInvocation.invocationWithMethodSignature(methodSignature); + invocation.selector = "completeTransition:"; + + export function completeTransition(didComplete: boolean) { + let didCompleteReference = new interop.Reference(interop.types.bool, didComplete); + invocation.setArgumentAtIndex(didCompleteReference, 2); + invocation.invokeWithTarget(this); + } +} + class AnimatedTransitioning extends NSObject implements UIViewControllerAnimatedTransitioning { public static ObjCProtocols = [UIViewControllerAnimatedTransitioning]; @@ -22,10 +34,8 @@ class AnimatedTransitioning extends NSObject implements UIViewControllerAnimated } public animateTransition(transitionContext: any): void { - let containerView = transitionContext.performSelector("containerView"); - var completion = (finished: boolean) => { - transitionContext.performSelectorWithObject("completeTransition:", finished); - } + let containerView = transitionContext.valueForKey("containerView"); + var completion = UIViewControllerAnimatedTransitioningMethods.completeTransition.bind(transitionContext); switch (this._operation) { case UINavigationControllerOperation.UINavigationControllerOperationPush: this._transitionType = "push"; break; case UINavigationControllerOperation.UINavigationControllerOperationPop: this._transitionType = "pop"; break; From 8339d3f51d8a9e83fedfdf93d2db861f8e7c4d51 Mon Sep 17 00:00:00 2001 From: Vladimir Enchev Date: Thu, 11 Feb 2016 11:12:14 +0200 Subject: [PATCH 8/8] Fixed null and undefined as Label text --- apps/tests/ui/label/label-tests.ts | 34 ++++++++++++++++++++++++++++++ ui/text-base/text-base.ts | 6 ++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/apps/tests/ui/label/label-tests.ts b/apps/tests/ui/label/label-tests.ts index e4df4e96b..f3634085c 100644 --- a/apps/tests/ui/label/label-tests.ts +++ b/apps/tests/ui/label/label-tests.ts @@ -89,6 +89,40 @@ export class LabelTest extends testModule.UITest { TKUnit.assertEqual(actualNative, expectedValue, "Native text not equal"); } + public test_Set_Text_Native_Null() { + var testLabel = this.testView; + var expectedValue = ""; + + testLabel.text = null; + var actualNative; + if (testLabel.ios) { + actualNative = testLabel.ios.text; + } + else { + this.waitUntilTestElementIsLoaded(); + actualNative = testLabel.android.getText(); + } + + TKUnit.assertEqual(actualNative, expectedValue, "Native text not equal"); + } + + public test_Set_Text_Native_Undefined() { + var testLabel = this.testView; + var expectedValue = ""; + + testLabel.text = undefined; + var actualNative; + if (testLabel.ios) { + actualNative = testLabel.ios.text; + } + else { + this.waitUntilTestElementIsLoaded(); + actualNative = testLabel.android.getText(); + } + + TKUnit.assertEqual(actualNative, expectedValue, "Native text not equal"); + } + public test_Set_BackgroundColor_TNS() { var label = this.testView; var expectedValue = new colorModule.Color("Red"); diff --git a/ui/text-base/text-base.ts b/ui/text-base/text-base.ts index 4461af956..e58d3ebd0 100644 --- a/ui/text-base/text-base.ts +++ b/ui/text-base/text-base.ts @@ -1,5 +1,6 @@ import definition = require("ui/text-base"); import view = require("ui/core/view"); +import types = require("utils/types"); import observable = require("data/observable"); import dependencyObservable = require("ui/core/dependency-observable"); import proxy = require("ui/core/proxy"); @@ -100,11 +101,12 @@ export class TextBase extends view.View implements definition.TextBase, formatte } public _onTextPropertyChanged(data: dependencyObservable.PropertyChangeData) { + var newValue = types.isNullOrUndefined(data.newValue) ? "" : data.newValue + ""; if (this.android) { - this.android.setText(data.newValue + ""); + this.android.setText(newValue); } else if (this.ios) { - this.ios.text = data.newValue + ""; + this.ios.text = newValue; this.style._updateTextDecoration(); this.style._updateTextTransform(); }