diff --git a/ui/frame/frame.ios.ts b/ui/frame/frame.ios.ts index c018cc505..5c9be26f1 100644 --- a/ui/frame/frame.ios.ts +++ b/ui/frame/frame.ios.ts @@ -4,6 +4,8 @@ import trace = require("trace"); import imageSource = require("image-source"); import pages = require("ui/page"); import enums = require("ui/enums"); +import utils = require("utils/utils"); +import view = require("ui/core/view"); declare var exports; require("utils/module-merge").merge(frameCommon, exports); @@ -15,7 +17,8 @@ var navDepth = 0; export class Frame extends frameCommon.Frame { private _ios: iOSFrame; private _paramToNavigate: any; - public shouldSkipNativePop: boolean = false; + public _shouldSkipNativePop: boolean = false; + public _navigateToEntry: definition.BackstackEntry; constructor() { super(); @@ -39,7 +42,7 @@ export class Frame extends frameCommon.Frame { this._paramToNavigate = param; } } - + public _navigateCore(backstackEntry: definition.BackstackEntry) { var viewController = backstackEntry.resolvedPage.ios; if (!viewController) { @@ -63,7 +66,7 @@ export class Frame extends frameCommon.Frame { public _goBackCore(entry: definition.NavigationEntry) { navDepth--; trace.write("Frame<" + this._domId + ">.popViewControllerAnimated depth = " + navDepth, trace.categories.Navigation); - if (!this.shouldSkipNativePop) { + if (!this._shouldSkipNativePop) { this._ios.controller.popViewControllerAnimated(this._getIsAnimatedNavigation(entry)); } } @@ -109,6 +112,32 @@ export class Frame extends frameCommon.Frame { } } + public onMeasure(widthMeasureSpec: number, heightMeasureSpec: number): void { + + var width = utils.layout.getMeasureSpecSize(widthMeasureSpec); + var widthMode = utils.layout.getMeasureSpecMode(widthMeasureSpec); + + var height = utils.layout.getMeasureSpecSize(heightMeasureSpec); + var heightMode = utils.layout.getMeasureSpecMode(heightMeasureSpec); + + var result = view.View.measureChild(this, this.currentPage, widthMeasureSpec, utils.layout.makeMeasureSpec(height - this.navigationBarHeight, heightMode)); + if (this._navigateToEntry) { + view.View.measureChild(this, this._navigateToEntry.resolvedPage, widthMeasureSpec, utils.layout.makeMeasureSpec(height - this.navigationBarHeight, heightMode)); + } + + var widthAndState = view.View.resolveSizeAndState(result.measuredWidth, width, widthMode, 0); + var heightAndState = view.View.resolveSizeAndState(result.measuredHeight, height, heightMode, 0); + + this.setMeasuredDimension(widthAndState, heightAndState); + } + + public onLayout(left: number, top: number, right: number, bottom: number): void { + view.View.layoutChild(this, this.currentPage, 0, this.navigationBarHeight, right - left, bottom - top); + if (this._navigateToEntry) { + view.View.layoutChild(this, this._navigateToEntry.resolvedPage, 0, this.navigationBarHeight, right - left, bottom - top); + } + } + public layoutNativeView(left: number, top: number, right: number, bottom: number): void { // We don't call super here because we set frame on our first subview. // This is done because when rotated in iOS7 there is rotation applied on the first subview on the Window which is our frame.nativeView.view. @@ -196,6 +225,29 @@ class UINavigationControllerImpl extends UINavigationController implements UINav this._owner._updateLayout(); } + public navigationControllerWillShowViewControllerAnimated(navigationController: UINavigationController, viewController: UIViewController, animated: boolean): void { + // This method is needed otherwise it will be too late and transition will completed before page is layouted. + var frame = this._owner; + var backStack = frame.backStack; + var currentEntry = backStack.length > 0 ? backStack[backStack.length - 1] : null; + var newEntry: definition.BackstackEntry = viewController[ENTRY]; + + var isBack = currentEntry && newEntry === currentEntry; + if (!isBack) { + var newPage = newEntry.resolvedPage; + + if (!frame._currentEntry) { + frame._currentEntry = newEntry; + } + else { + frame._navigateToEntry = newEntry; + } + + frame._addView(newPage); + frame.populateMenuItems(newPage); + } + } + public navigationControllerDidShowViewControllerAnimated(navigationController: UINavigationController, viewController: UIViewController, animated: boolean): void { var frame: Frame = this._owner; @@ -203,26 +255,26 @@ class UINavigationControllerImpl extends UINavigationController implements UINav var currentEntry = backStack.length > 0 ? backStack[backStack.length - 1] : null; var newEntry: definition.BackstackEntry = viewController[ENTRY]; - if (newEntry === currentEntry && currentEntry) { + var isBack: boolean = currentEntry && newEntry === currentEntry; + if (isBack) { try { - frame.shouldSkipNativePop = true; + frame._shouldSkipNativePop = true; frame.goBack(); } finally { - frame.shouldSkipNativePop = false; + frame._shouldSkipNativePop = false; } } var page = frame.currentPage; - if (page) { + if (page && isBack) { frame._removeView(page); } var newPage = newEntry.resolvedPage; + frame._navigateToEntry = null; frame._currentEntry = newEntry; - frame._addView(newPage); - frame.populateMenuItems(newPage); frame.updateNavigationBar(); // notify the page diff --git a/ui/image/image-common.ts b/ui/image/image-common.ts index 998d27f2d..a9b491128 100644 --- a/ui/image/image-common.ts +++ b/ui/image/image-common.ts @@ -65,7 +65,8 @@ export class Image extends view.View implements definition.Image { IMAGE, new proxy.PropertyMetadata( undefined, - dependencyObservable.PropertyMetadataSettings.AffectsLayout + // None on purpose. for iOS we trigger it manually if needed. Android layout handles it. + dependencyObservable.PropertyMetadataSettings.None ) ); diff --git a/ui/list-view/list-view.ios.ts b/ui/list-view/list-view.ios.ts index 4bff16324..4d022cc28 100644 --- a/ui/list-view/list-view.ios.ts +++ b/ui/list-view/list-view.ios.ts @@ -186,7 +186,7 @@ export class ListView extends common.ListView { public refresh() { this._ios.reloadData(); - this.requestLayout(); + this.requestLayout(); } public getHeight(index: number): number { @@ -227,21 +227,22 @@ export class ListView extends common.ListView { public _prepareCell(tableCell: UITableViewCell, indexPath: NSIndexPath): number { var cell: any = tableCell; - if (!cell.view) { - cell.view = this._getItemTemplateContent(indexPath.row); - } - - var args = notifyForItemAtIndex(this, cell, ITEMLOADING, indexPath); - var view = cell.view = args.view || this._getDefaultItemContent(indexPath.row); - - if (view && !view.parent && view.ios) { - cell.contentView.addSubview(view.ios); - this._addView(view); - } - var cellHeight: number; + try { this._preparingCell = true; + if (!cell.view) { + cell.view = this._getItemTemplateContent(indexPath.row); + } + + var args = notifyForItemAtIndex(this, cell, ITEMLOADING, indexPath); + var view = cell.view = args.view || this._getDefaultItemContent(indexPath.row); + + if (view && !view.parent && view.ios) { + cell.contentView.addSubview(view.ios); + this._addView(view); + } + this._prepareItem(view, indexPath.row); cellHeight = this._layoutCell(view, indexPath); }