mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-16 11:42:04 +08:00
Tabs animation and selected index fixes (#8377)
* fix(tabs): animation freeze when chaning tabs * fix(tabs): poper item selecting programically
This commit is contained in:
@ -2934,7 +2934,7 @@ export abstract class ViewBase extends Observable {
|
|||||||
// (undocumented)
|
// (undocumented)
|
||||||
_setupAsRootView(context: any): void;
|
_setupAsRootView(context: any): void;
|
||||||
_setupUI(context: any /* android.content.Context */, atIndex?: number): void;
|
_setupUI(context: any /* android.content.Context */, atIndex?: number): void;
|
||||||
_shouldDelayLoad(): boolean;
|
_shouldDelayLayout(): boolean;
|
||||||
showModal(moduleName: string, modalOptions: ShowModalOptions): ViewBase;
|
showModal(moduleName: string, modalOptions: ShowModalOptions): ViewBase;
|
||||||
showModal(view: ViewBase, modalOptions: ShowModalOptions): ViewBase;
|
showModal(view: ViewBase, modalOptions: ShowModalOptions): ViewBase;
|
||||||
public readonly style: Style;
|
public readonly style: Style;
|
||||||
|
@ -474,7 +474,7 @@ export abstract class ViewBase extends Observable {
|
|||||||
* When returning true the callLoaded method will be run in setTimeout
|
* When returning true the callLoaded method will be run in setTimeout
|
||||||
* Method is intended to be overridden by inheritors and used as "protected"
|
* Method is intended to be overridden by inheritors and used as "protected"
|
||||||
*/
|
*/
|
||||||
_shouldDelayLoad(): boolean;
|
_shouldDelayLayout(): boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
|
@ -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
|
@profile
|
||||||
public requestLayout(): void {
|
public requestLayout(): void {
|
||||||
// Default implementation for non View instances (like TabViewItem).
|
// Default implementation for non View instances (like TabViewItem).
|
||||||
const parent = this.parent;
|
const parent = this.parent;
|
||||||
if (parent) {
|
if (parent) {
|
||||||
parent.requestLayout();
|
this.performLayout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -615,15 +627,11 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
|
|||||||
|
|
||||||
public loadView(view: ViewBase): void {
|
public loadView(view: ViewBase): void {
|
||||||
if (view && !view.isLoaded) {
|
if (view && !view.isLoaded) {
|
||||||
if (this._shouldDelayLoad()) {
|
|
||||||
setTimeout(() => view.callLoaded());
|
|
||||||
} else {
|
|
||||||
view.callLoaded();
|
view.callLoaded();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public _shouldDelayLoad(): boolean {
|
public _shouldDelayLayout(): boolean {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ export class Page extends PageBase {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
public _shouldDelayLoad(): boolean {
|
public _shouldDelayLayout(): boolean {
|
||||||
return this._frame && this._frame._animationInProgress;
|
return this._frame && this._frame._animationInProgress;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
|
import { TabContentItem } from "../tab-navigation-base/tab-content-item";
|
||||||
import { TabStrip } from "../tab-navigation-base/tab-strip";
|
import { TabStrip } from "../tab-navigation-base/tab-strip";
|
||||||
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
|
import { TabStripItem } from "../tab-navigation-base/tab-strip-item";
|
||||||
import { TextTransform } from "../text-base";
|
import { TextTransform, ViewBase } from "../text-base";
|
||||||
|
|
||||||
// Requires
|
// Requires
|
||||||
import { Color } from "../../color";
|
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
|
// TODO: investigate why this call is necessary to actually toggle item appearance
|
||||||
this.viewController.tabBar.sizeToFit();
|
this.viewController.tabBar.sizeToFit();
|
||||||
this.tabStrip.setNativeView(this.viewController.tabBar);
|
this.tabStrip.setNativeView(this.viewController.tabBar);
|
||||||
|
if (this.selectedIndex) {
|
||||||
|
this.viewController.tabBar.setSelectedItemAnimated(this.tabBarItems[this.selectedIndex], false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// const length = items ? items.length : 0;
|
// const length = items ? items.length : 0;
|
||||||
@ -1066,6 +1069,17 @@ export class Tabs extends TabsBase {
|
|||||||
this._ios.tabBar.tintColor = nativeColor;
|
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) {
|
[selectedIndexProperty.setNative](value: number) {
|
||||||
// TODO
|
// TODO
|
||||||
// if (traceEnabled()) {
|
// if (traceEnabled()) {
|
||||||
@ -1092,17 +1106,11 @@ export class Tabs extends TabsBase {
|
|||||||
|
|
||||||
this._currentNativeSelectedIndex = value;
|
this._currentNativeSelectedIndex = value;
|
||||||
|
|
||||||
let itemControllerOwner = null;
|
// do not make layout changes while the animation is in progress https://stackoverflow.com/a/47031524/613113
|
||||||
if (itemController._owner) {
|
this.visitFrames(item, frame => frame._animationInProgress = true);
|
||||||
let itemControllerOwner = <Frame>itemController._owner.get();
|
|
||||||
// do not load new views while the animation is in progress https://stackoverflow.com/a/47031524/613113
|
|
||||||
itemControllerOwner._animationInProgress = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.viewController.setViewControllersDirectionAnimatedCompletion(controllers, navigationDirection, true, (finished: boolean) => {
|
this.viewController.setViewControllersDirectionAnimatedCompletion(controllers, navigationDirection, true, (finished: boolean) => {
|
||||||
if (itemControllerOwner) {
|
this.visitFrames(item, frame => frame._animationInProgress = false);
|
||||||
itemControllerOwner._animationInProgress = false;
|
|
||||||
}
|
|
||||||
if (finished) {
|
if (finished) {
|
||||||
// HACK: UIPageViewController fix; see https://stackoverflow.com/a/17330606
|
// HACK: UIPageViewController fix; see https://stackoverflow.com/a/17330606
|
||||||
invokeOnRunLoop(() => this.viewController.setViewControllersDirectionAnimatedCompletion(controllers, navigationDirection, false, null));
|
invokeOnRunLoop(() => this.viewController.setViewControllersDirectionAnimatedCompletion(controllers, navigationDirection, false, null));
|
||||||
|
Reference in New Issue
Block a user