diff --git a/api-reports/NativeScript.api.md b/api-reports/NativeScript.api.md index c6bf4bbf8..6bb4354fc 100644 --- a/api-reports/NativeScript.api.md +++ b/api-reports/NativeScript.api.md @@ -2934,7 +2934,7 @@ export abstract class ViewBase extends Observable { // (undocumented) _setupAsRootView(context: any): void; _setupUI(context: any /* android.content.Context */, atIndex?: number): void; - _shouldDelayLoad(): boolean; + _shouldDelayLayout(): boolean; showModal(moduleName: string, modalOptions: ShowModalOptions): ViewBase; showModal(view: ViewBase, modalOptions: ShowModalOptions): ViewBase; public readonly style: Style; diff --git a/nativescript-core/ui/core/view-base/view-base.d.ts b/nativescript-core/ui/core/view-base/view-base.d.ts index a8fa7dd25..4ad892f64 100644 --- a/nativescript-core/ui/core/view-base/view-base.d.ts +++ b/nativescript-core/ui/core/view-base/view-base.d.ts @@ -474,7 +474,7 @@ export abstract class ViewBase extends Observable { * When returning true the callLoaded method will be run in setTimeout * Method is intended to be overridden by inheritors and used as "protected" */ - _shouldDelayLoad(): boolean; + _shouldDelayLayout(): boolean; /** * @private diff --git a/nativescript-core/ui/core/view-base/view-base.ts b/nativescript-core/ui/core/view-base/view-base.ts index c464a362a..2046190fa 100644 --- a/nativescript-core/ui/core/view-base/view-base.ts +++ b/nativescript-core/ui/core/view-base/view-base.ts @@ -561,12 +561,24 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition } } + private performLayout(currentRun = 0) { + // if there's an animation in progress we need to delay the layout + // we've added a guard of 5000 milliseconds execution + // to make sure that the layout will happen even if the animation haven't finished in 5 seconds + if (this._shouldDelayLayout() && currentRun < 100) { + setTimeout(() => this.performLayout(currentRun), currentRun); + currentRun++; + } else { + this.parent.requestLayout(); + } + } + @profile public requestLayout(): void { // Default implementation for non View instances (like TabViewItem). const parent = this.parent; if (parent) { - parent.requestLayout(); + this.performLayout(); } } @@ -615,15 +627,11 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition public loadView(view: ViewBase): void { if (view && !view.isLoaded) { - if (this._shouldDelayLoad()) { - setTimeout(() => view.callLoaded()); - } else { - view.callLoaded(); - } + view.callLoaded(); } } - public _shouldDelayLoad(): boolean { + public _shouldDelayLayout(): boolean { return false; } diff --git a/nativescript-core/ui/page/page.ios.ts b/nativescript-core/ui/page/page.ios.ts index 576eb25a8..e63742f2b 100644 --- a/nativescript-core/ui/page/page.ios.ts +++ b/nativescript-core/ui/page/page.ios.ts @@ -348,7 +348,7 @@ export class Page extends PageBase { // } - public _shouldDelayLoad(): boolean { + public _shouldDelayLayout(): boolean { return this._frame && this._frame._animationInProgress; } diff --git a/nativescript-core/ui/tabs/tabs.ios.ts b/nativescript-core/ui/tabs/tabs.ios.ts index 621a520d1..9a59ce5b1 100644 --- a/nativescript-core/ui/tabs/tabs.ios.ts +++ b/nativescript-core/ui/tabs/tabs.ios.ts @@ -2,7 +2,7 @@ import { TabContentItem } from "../tab-navigation-base/tab-content-item"; import { TabStrip } from "../tab-navigation-base/tab-strip"; import { TabStripItem } from "../tab-navigation-base/tab-strip-item"; -import { TextTransform } from "../text-base"; +import { TextTransform, ViewBase } from "../text-base"; // Requires import { Color } from "../../color"; @@ -873,6 +873,9 @@ export class Tabs extends TabsBase { // TODO: investigate why this call is necessary to actually toggle item appearance this.viewController.tabBar.sizeToFit(); this.tabStrip.setNativeView(this.viewController.tabBar); + if (this.selectedIndex) { + this.viewController.tabBar.setSelectedItemAnimated(this.tabBarItems[this.selectedIndex], false); + } } // const length = items ? items.length : 0; @@ -1066,6 +1069,17 @@ export class Tabs extends TabsBase { this._ios.tabBar.tintColor = nativeColor; } + private visitFrames(view: ViewBase, operation: (frame: Frame) => {}) { + if (view instanceof Frame) { + operation(view); + } + view.eachChild(child => { + this.visitFrames(child, operation); + + return true; + }); + } + [selectedIndexProperty.setNative](value: number) { // TODO // if (traceEnabled()) { @@ -1092,17 +1106,11 @@ export class Tabs extends TabsBase { this._currentNativeSelectedIndex = value; - let itemControllerOwner = null; - if (itemController._owner) { - let itemControllerOwner = itemController._owner.get(); - // do not load new views while the animation is in progress https://stackoverflow.com/a/47031524/613113 - itemControllerOwner._animationInProgress = true; - } + // do not make layout changes while the animation is in progress https://stackoverflow.com/a/47031524/613113 + this.visitFrames(item, frame => frame._animationInProgress = true); this.viewController.setViewControllersDirectionAnimatedCompletion(controllers, navigationDirection, true, (finished: boolean) => { - if (itemControllerOwner) { - itemControllerOwner._animationInProgress = false; - } + this.visitFrames(item, frame => frame._animationInProgress = false); if (finished) { // HACK: UIPageViewController fix; see https://stackoverflow.com/a/17330606 invokeOnRunLoop(() => this.viewController.setViewControllersDirectionAnimatedCompletion(controllers, navigationDirection, false, null));