From f5905f072df63cb6e6f5497c4952664fd33cb75c Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Wed, 21 Dec 2016 12:02:02 +0200 Subject: [PATCH] fix tab-view, segmented-bar, action-bar, all ViewBases (#3340) --- apps/.vscode/settings.json | 3 + apps/app/package.json | 2 +- tests/app/ui/repeater/repeater-tests.ts | 8 +- .../ui/action-bar/action-bar-common.ts | 23 ++++- .../ui/content-view/content-view.ts | 7 +- tns-core-modules/ui/core/view-base.ts | 33 ++++--- tns-core-modules/ui/core/view-common.ts | 17 ++-- tns-core-modules/ui/core/view.android.ts | 52 +++++------ tns-core-modules/ui/core/view.d.ts | 15 ++-- tns-core-modules/ui/definitions.d.ts | 2 +- tns-core-modules/ui/frame/frame-common.ts | 2 +- .../ui/layouts/layout-base-common.ts | 6 +- .../ui/list-view/list-view.android.ts | 2 +- .../ui/list-view/list-view.ios.ts | 2 +- tns-core-modules/ui/page/page-common.ts | 4 +- .../proxy-view-container.ts | 12 +-- tns-core-modules/ui/repeater/repeater.ts | 2 +- .../ui/segmented-bar/segmented-bar-common.ts | 5 +- .../ui/segmented-bar/segmented-bar.ios.ts | 7 +- .../ui/tab-view/tab-view-common.ts | 53 +++-------- .../ui/tab-view/tab-view.android.ts | 90 ++++++++----------- tns-core-modules/ui/tab-view/tab-view.ios.ts | 77 +++++----------- 22 files changed, 175 insertions(+), 249 deletions(-) create mode 100644 apps/.vscode/settings.json diff --git a/apps/.vscode/settings.json b/apps/.vscode/settings.json new file mode 100644 index 000000000..c7c1623bc --- /dev/null +++ b/apps/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "typescript.tsdk": "./node_modules/typescript/lib" +} \ No newline at end of file diff --git a/apps/app/package.json b/apps/app/package.json index 711929cac..b83961d5d 100644 --- a/apps/app/package.json +++ b/apps/app/package.json @@ -1,4 +1,4 @@ { "name": "tns-samples-apps", - "main": "ui-tests-app/app.js" + "main": "cuteness.io/app.js" } diff --git a/tests/app/ui/repeater/repeater-tests.ts b/tests/app/ui/repeater/repeater-tests.ts index 938ea9d9e..601553227 100644 --- a/tests/app/ui/repeater/repeater-tests.ts +++ b/tests/app/ui/repeater/repeater-tests.ts @@ -353,12 +353,12 @@ export var test_RepeaterItemsGestureBindings = function () { hasObservers = gestureObservers ? gestureObservers.length > 0 : false; } else if (childItem instanceof layoutBaseModule.LayoutBase) { - childItem._eachChildView(eachChildCallback); + childItem.eachChildView(eachChildCallback); } return true; } - repeater._eachChildView(eachChildCallback); + repeater.eachChildView(eachChildCallback); TKUnit.assertEqual(hasObservers, true, "Every item should have tap observer!"); } @@ -380,12 +380,12 @@ export var test_RepeaterItemsParentBindingsShouldWork = function () { } } else if (childItem instanceof layoutBaseModule.LayoutBase) { - childItem._eachChildView(eachChildCallback); + childItem.eachChildView(eachChildCallback); } return true; } - repeater._eachChildView(eachChildCallback); + repeater.eachChildView(eachChildCallback); TKUnit.assertEqual(testPass, true, "Every item should have text bound to Page binding context!"); } diff --git a/tns-core-modules/ui/action-bar/action-bar-common.ts b/tns-core-modules/ui/action-bar/action-bar-common.ts index b3a04066d..aca8e8681 100644 --- a/tns-core-modules/ui/action-bar/action-bar-common.ts +++ b/tns-core-modules/ui/action-bar/action-bar-common.ts @@ -141,9 +141,10 @@ export class ActionBarBase extends View implements ActionBarDefinition { // this._actionItems.getItems().forEach((item, i, arr) => { item.bindingContext = newValue; }); // } - public _eachChildView(callback: (child: View) => boolean) { - if (this.titleView) { - callback(this.titleView); + public eachChildView(callback: (child: View) => boolean) { + const titleView = this.titleView; + if (titleView) { + callback(titleView); } this.actionItems.getItems().forEach((actionItem) => { @@ -153,6 +154,22 @@ export class ActionBarBase extends View implements ActionBarDefinition { }); } + public eachChild(callback: (child: ViewBase) => boolean) { + const titleView = this.titleView; + if (titleView) { + callback(titleView); + } + + const navigationButton = this._navigationButton; + if (navigationButton) { + callback(navigationButton); + } + + this.actionItems.getItems().forEach((actionItem) => { + callback(actionItem); + }); + } + public _isEmpty(): boolean { if (this.title || this.titleView || diff --git a/tns-core-modules/ui/content-view/content-view.ts b/tns-core-modules/ui/content-view/content-view.ts index 9f5daa1e3..b14432781 100644 --- a/tns-core-modules/ui/content-view/content-view.ts +++ b/tns-core-modules/ui/content-view/content-view.ts @@ -60,9 +60,10 @@ export class ContentView extends CustomLayoutView implements ContentViewDefiniti } } - public _eachChildView(callback: (child: View) => boolean) { - if (this._content) { - callback(this._content); + public eachChildView(callback: (child: View) => boolean) { + const content = this._content; + if (content) { + callback(content); } } diff --git a/tns-core-modules/ui/core/view-base.ts b/tns-core-modules/ui/core/view-base.ts index 9c81d9c15..3912a3d29 100644 --- a/tns-core-modules/ui/core/view-base.ts +++ b/tns-core-modules/ui/core/view-base.ts @@ -91,6 +91,8 @@ export function eachDescendant(view: ViewBaseDefinition, callback: (child: ViewB view.eachChild(localCallback); } +let viewIdCounter = 0; + export class ViewBase extends Observable implements ViewBaseDefinition { private _updatingJSPropertiesDict = {}; private _style: Style; @@ -106,9 +108,12 @@ export class ViewBase extends Observable implements ViewBaseDefinition { public id: string; public className: string; + public _domId: number; + public _cssState: CssState; constructor() { super(); + this._domId = viewIdCounter++; this._style = new Style(this); } @@ -154,17 +159,11 @@ export class ViewBase extends Observable implements ViewBaseDefinition { this._emit("loaded"); } - get _childrenCount(): number { - return 0; - } - public _loadEachChildView() { - if (this._childrenCount > 0) { - this.eachChild((child) => { - child.onLoaded(); - return true; - }); - } + this.eachChild((child) => { + child.onLoaded(); + return true; + }); } public onUnloaded() { @@ -175,15 +174,13 @@ export class ViewBase extends Observable implements ViewBaseDefinition { } private _unloadEachChildView() { - if (this._childrenCount > 0) { - this.eachChild((child) => { - if (child.isLoaded) { - child.onUnloaded(); - } + this.eachChild((child) => { + if (child.isLoaded) { + child.onUnloaded(); + } - return true; - }); - } + return true; + }); } public _applyStyleFromScope() { diff --git a/tns-core-modules/ui/core/view-common.ts b/tns-core-modules/ui/core/view-common.ts index e3d512844..5f35a8db5 100644 --- a/tns-core-modules/ui/core/view-common.ts +++ b/tns-core-modules/ui/core/view-common.ts @@ -66,8 +66,6 @@ export function PseudoClassHandler(...pseudoClasses: string[]): MethodDecorator } } -let viewIdCounter = 0; - export abstract class ViewCommon extends ViewBase implements ViewDefinition { // Dynamic properties. left: Length; @@ -97,9 +95,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { private _cssType: string; private _updatingInheritedProperties: boolean; - - - public _domId: number; public _isAddedToNativeVisualTree: boolean; public _gestureObservers = {}; @@ -107,8 +102,6 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { constructor() { super(); - - this._domId = viewIdCounter++; this._goToVisualState("normal"); } @@ -794,13 +787,13 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { //@endios public eachChild(callback: (child: ViewBase) => boolean): void { - this._eachChildView(callback); + this.eachChildView(callback); } - public _eachChildView(callback: (view: ViewDefinition) => boolean) { + public eachChildView(callback: (view: ViewDefinition) => boolean) { // } - + _childIndexToNativeChildIndex(index?: number): number { return index; } @@ -857,8 +850,8 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition { // // return true; // // }); // } - - /** + + /** * Method is intended to be overridden by inheritors and used as "protected". */ public _addViewToNativeVisualTree(view: ViewDefinition, atIndex?: number): boolean { diff --git a/tns-core-modules/ui/core/view.android.ts b/tns-core-modules/ui/core/view.android.ts index 6063e2c15..103cc3385 100644 --- a/tns-core-modules/ui/core/view.android.ts +++ b/tns-core-modules/ui/core/view.android.ts @@ -148,23 +148,18 @@ export class View extends ViewCommon { traceNotifyEvent(this, "_onAttached"); } - if (this._childrenCount > 0) { - // Notify each child for the _onAttached event - let that = this; - // TODO: This should be done in a call - let eachChild = (child: View): boolean => { - child._onAttached(context); - if (!child._isAddedToNativeVisualTree) { - // since we have lazy loading of the android widgets, we need to add the native instances at this point. - child._isAddedToNativeVisualTree = that._addViewToNativeVisualTree(child); - } - - // copy all the locally cached values to the native android widget - return true; + // Notify each child for the _onAttached event + this.eachChildView((child) => { + child._onAttached(context); + if (!child._isAddedToNativeVisualTree) { + // since we have lazy loading of the android widgets, we need to add the native instances at this point. + child._isAddedToNativeVisualTree = this._addViewToNativeVisualTree(child); } - this._eachChildView(eachChild); - } + return true; + }); + + // copy all the locally cached values to the native android widget applyNativeSetters(this); } @@ -173,20 +168,16 @@ export class View extends ViewCommon { traceWrite(`${this}._onDetached(force)`, traceCategories.VisualTreeEvents); } - if (this._childrenCount > 0) { - // Detach children first - let that = this; - let eachChild = function (child: View): boolean { - if (child._isAddedToNativeVisualTree) { - that._removeViewFromNativeVisualTree(child); - } - if (child._context) { - child._onDetached(force); - } - return true; + // Detach children first + this.eachChildView((child: View) => { + if (child._isAddedToNativeVisualTree) { + this._removeViewFromNativeVisualTree(child); } - this._eachChildView(eachChild); - } + if (child._context) { + child._onDetached(force); + } + return true; + }); this._clearAndroidReference(); this._context = undefined; @@ -215,6 +206,7 @@ export class View extends ViewCommon { if (traceEnabled) { traceWrite(`${this}._onContextChanged`, traceCategories.VisualTreeEvents); } + this._createUI(); // Ensure layout params if (this._nativeView && !this._nativeView.getLayoutParams()) { @@ -432,7 +424,7 @@ export class View extends ViewCommon { return Visibility.HIDDEN; case android.view.View.GONE: return Visibility.COLLAPSE; - default: + default: throw new Error(`Unsupported android.view.View visibility: ${nativeVisibility}. Currently supported values are android.view.View.VISIBLE, android.view.View.INVISIBLE, android.view.View.GONE.`); } } @@ -447,7 +439,7 @@ export class View extends ViewCommon { case Visibility.COLLAPSE: this.nativeView.setVisibility(android.view.View.GONE); break; - default: + default: throw new Error(`Invalid visibility value: ${value}. Valid values are: "${Visibility.VISIBLE}", "${Visibility.HIDDEN}", "${Visibility.COLLAPSE}".`); } } diff --git a/tns-core-modules/ui/core/view.d.ts b/tns-core-modules/ui/core/view.d.ts index 5fbfef5f8..0fbe34a20 100644 --- a/tns-core-modules/ui/core/view.d.ts +++ b/tns-core-modules/ui/core/view.d.ts @@ -562,32 +562,27 @@ declare module "ui/core/view" { _removeFromSuperview(); public _applyXmlAttribute(attribute: string, value: any): boolean; + public eachChildView(callback: (view: View) => boolean): void; + //@private /** * A property has changed on the native side directly - e.g. the user types in a TextField. */ public nativePropertyChanged(property: Property, newValue: any): void; - public bind(options: BindingOptions, source?: any): void; - public unbind(property: string): void; - - isCollapsed: boolean; + isLayoutRequired: boolean; - _gestureObservers: any; // _isInheritedChange(): boolean; - _domId: number; _isAddedToNativeVisualTree: boolean; /** * Performs the core logic of adding a child view to the native visual tree. Returns true if the view's native representation has been successfully added, false otherwise. */ - _addViewToNativeVisualTree(view: View, atIndex?: number): boolean; - _removeViewFromNativeVisualTree(view: View): void; + _addViewToNativeVisualTree(view: ViewBase, atIndex?: number): boolean; + _removeViewFromNativeVisualTree(view: ViewBase): void; - _eachChildView(callback: (child: View) => boolean); - _childrenCount: number; _onAttached(context: any /* android.content.Context */): void; _onContextChanged(): void; diff --git a/tns-core-modules/ui/definitions.d.ts b/tns-core-modules/ui/definitions.d.ts index 64d592831..de8380f07 100644 --- a/tns-core-modules/ui/definitions.d.ts +++ b/tns-core-modules/ui/definitions.d.ts @@ -103,7 +103,7 @@ declare module "ui/core/view-base" { public _removeView(view: ViewBase): void; public _parentChanged(oldParent: ViewBase): void; - _childrenCount: number; + _domId: number; _cssState: any /* "ui/styling/style-scope" */; _setCssState(next: any /* "ui/styling/style-scope" */); diff --git a/tns-core-modules/ui/frame/frame-common.ts b/tns-core-modules/ui/frame/frame-common.ts index 8f27d8293..eb9ab9a31 100644 --- a/tns-core-modules/ui/frame/frame-common.ts +++ b/tns-core-modules/ui/frame/frame-common.ts @@ -396,7 +396,7 @@ export class FrameBase extends CustomLayoutView implements FrameDefinition { return 0; } - public _eachChildView(callback: (child: View) => boolean) { + public eachChildView(callback: (child: View) => boolean) { if (this.currentPage) { callback(this.currentPage); } diff --git a/tns-core-modules/ui/layouts/layout-base-common.ts b/tns-core-modules/ui/layouts/layout-base-common.ts index 099112fce..1a8169fea 100644 --- a/tns-core-modules/ui/layouts/layout-base-common.ts +++ b/tns-core-modules/ui/layouts/layout-base-common.ts @@ -90,7 +90,7 @@ export class LayoutBaseCommon extends CustomLayoutView implements LayoutBaseDefi return result; } - public _eachChildView(callback: (child: View) => boolean): void { + public eachChildView(callback: (child: View) => boolean): void { for (let i = 0, length = this._subViews.length; i < length; i++) { const retVal = callback(this._subViews[i]); if (retVal === false) { @@ -98,11 +98,11 @@ export class LayoutBaseCommon extends CustomLayoutView implements LayoutBaseDefi } } } - + public eachLayoutChild(callback: (child: View, isLast: boolean) => void): void { var lastChild: View = null; - this._eachChildView((cv) => { + this.eachChildView((cv) => { cv._eachLayoutView((lv) => { if (lastChild && !lastChild.isCollapsed) { callback(lastChild, false); diff --git a/tns-core-modules/ui/list-view/list-view.android.ts b/tns-core-modules/ui/list-view/list-view.android.ts index 7c7f06338..68bf71038 100644 --- a/tns-core-modules/ui/list-view/list-view.android.ts +++ b/tns-core-modules/ui/list-view/list-view.android.ts @@ -90,7 +90,7 @@ export class ListView extends ListViewBase { return this._realizedItems.size; } - public _eachChildView(callback: (child: View) => boolean): void { + public eachChildView(callback: (child: View) => boolean): void { this._realizedItems.forEach((view, nativeView, map) => { if (view.parent instanceof ListView) { callback(view); diff --git a/tns-core-modules/ui/list-view/list-view.ios.ts b/tns-core-modules/ui/list-view/list-view.ios.ts index ffa0d797a..d96829c18 100644 --- a/tns-core-modules/ui/list-view/list-view.ios.ts +++ b/tns-core-modules/ui/list-view/list-view.ios.ts @@ -227,7 +227,7 @@ export class ListView extends ListViewBase { return this._map.size; } - public _eachChildView(callback: (child: View) => boolean): void { + public eachChildView(callback: (child: View) => boolean): void { this._map.forEach((view, key) => { callback(view); }); diff --git a/tns-core-modules/ui/page/page-common.ts b/tns-core-modules/ui/page/page-common.ts index 1b7bfd158..ddab1c62b 100644 --- a/tns-core-modules/ui/page/page-common.ts +++ b/tns-core-modules/ui/page/page-common.ts @@ -252,8 +252,8 @@ export class PageBase extends ContentView implements PageDefinition { return this._styleScope; } - public _eachChildView(callback: (child: View) => boolean) { - super._eachChildView(callback); + public eachChildView(callback: (child: View) => boolean) { + super.eachChildView(callback); callback(this.actionBar); } diff --git a/tns-core-modules/ui/proxy-view-container/proxy-view-container.ts b/tns-core-modules/ui/proxy-view-container/proxy-view-container.ts index 29305dbcc..2fc873248 100644 --- a/tns-core-modules/ui/proxy-view-container/proxy-view-container.ts +++ b/tns-core-modules/ui/proxy-view-container/proxy-view-container.ts @@ -38,7 +38,7 @@ export class ProxyViewContainer extends LayoutBase implements ProxyViewContainer public _getNativeViewsCount(): number { let result = 0; - this._eachChildView((cv) => { + this.eachChildView((cv) => { result += cv._getNativeViewsCount(); return true; }); @@ -47,7 +47,7 @@ export class ProxyViewContainer extends LayoutBase implements ProxyViewContainer } public _eachLayoutView(callback: (View) => void): void { - this._eachChildView((cv) => { + this.eachChildView((cv) => { if (!cv.isCollapsed) { cv._eachLayoutView(callback); } @@ -99,7 +99,7 @@ export class ProxyViewContainer extends LayoutBase implements ProxyViewContainer public _addToSuperview(superview: any, atIndex?: number): boolean { let index = 0; - this._eachChildView((cv) => { + this.eachChildView((cv) => { if (!cv._isAddedToNativeVisualTree) { cv._isAddedToNativeVisualTree = this._addViewToNativeVisualTree(cv, index++); } @@ -110,7 +110,7 @@ export class ProxyViewContainer extends LayoutBase implements ProxyViewContainer } public _removeFromSuperview() { - this._eachChildView((cv) => { + this.eachChildView((cv) => { if (cv._isAddedToNativeVisualTree) { this._removeViewFromNativeVisualTree(cv); } @@ -147,12 +147,12 @@ export class ProxyViewContainer extends LayoutBase implements ProxyViewContainer const oldLayout = oldParent; if (addingToParent && newLayout instanceof LayoutBase) { - this._eachChildView((child) => { + this.eachChildView((child) => { newLayout._registerLayoutChild(child); return true; }); } else if (oldLayout instanceof LayoutBase) { - this._eachChildView((child) => { + this.eachChildView((child) => { oldLayout._unregisterLayoutChild(child); return true; }); diff --git a/tns-core-modules/ui/repeater/repeater.ts b/tns-core-modules/ui/repeater/repeater.ts index 6e3cba330..90902e419 100644 --- a/tns-core-modules/ui/repeater/repeater.ts +++ b/tns-core-modules/ui/repeater/repeater.ts @@ -92,7 +92,7 @@ export class Repeater extends CustomLayoutView implements RepeaterDefinition { return count; } - public _eachChildView(callback: (child: View) => boolean) { + public eachChildView(callback: (child: View) => boolean) { if (this.itemsLayout) { callback(this.itemsLayout); } diff --git a/tns-core-modules/ui/segmented-bar/segmented-bar-common.ts b/tns-core-modules/ui/segmented-bar/segmented-bar-common.ts index 694122cd4..670a7c0a2 100644 --- a/tns-core-modules/ui/segmented-bar/segmented-bar-common.ts +++ b/tns-core-modules/ui/segmented-bar/segmented-bar-common.ts @@ -12,7 +12,6 @@ export module knownCollections { export abstract class SegmentedBarItemBase extends ViewBase implements SegmentedBarItemDefinition { private _title: string = ""; - public _parent: SegmentedBarBase; get title(): string { return this._title; @@ -64,8 +63,8 @@ export abstract class SegmentedBarBase extends View implements SegmentedBarDefin } // TODO: Make _addView to keep its children so this method is not needed! - public _eachChildView(callback: (child: ViewBase) => boolean): void { - let items = this.items; + public eachChild(callback: (child: ViewBase) => boolean): void { + const items = this.items; if (items) { items.forEach((item, i) => { callback(item); diff --git a/tns-core-modules/ui/segmented-bar/segmented-bar.ios.ts b/tns-core-modules/ui/segmented-bar/segmented-bar.ios.ts index 06b16849b..7730cd6b4 100644 --- a/tns-core-modules/ui/segmented-bar/segmented-bar.ios.ts +++ b/tns-core-modules/ui/segmented-bar/segmented-bar.ios.ts @@ -9,11 +9,12 @@ export * from "./segmented-bar-common"; export class SegmentedBarItem extends SegmentedBarItemBase { public _update() { - if (this._parent) { - let tabIndex = this._parent.items.indexOf(this); + const parent = this.parent; + if (parent) { + let tabIndex = parent.items.indexOf(this); let title = this.title; title = (title === null || title === undefined) ? "" : title; - this._parent.ios.setTitleForSegmentAtIndex(title, tabIndex); + parent.ios.setTitleForSegmentAtIndex(title, tabIndex); } } } diff --git a/tns-core-modules/ui/tab-view/tab-view-common.ts b/tns-core-modules/ui/tab-view/tab-view-common.ts index 6e09a3da5..9fbc4ff69 100644 --- a/tns-core-modules/ui/tab-view/tab-view-common.ts +++ b/tns-core-modules/ui/tab-view/tab-view-common.ts @@ -87,37 +87,6 @@ export class TabViewBase extends View implements TabViewDefinition, AddChildFrom } } - public _removeTabs(oldItems: Array) { - for (let i = 0, length = oldItems.length; i < length; i++) { - let oldItem = oldItems[i]; - - if (!oldItem) { - throw new Error("TabViewItem at index " + i + " is undefined."); - } - - if (!oldItem.view) { - throw new Error("TabViewItem at index " + i + " does not have a view."); - } - this._removeView(oldItem); - } - } - - public _addTabs(newItems: Array) { - // Validate that all items are ok before the native _addTabs code runs. - for (let i = 0, length = newItems.length; i < length; i++) { - let newItem = newItems[i]; - - if (!newItem) { - throw new Error(`TabViewItem at index ${i} is undefined.`); - } - - if (!newItem.view) { - throw new Error(`TabViewItem at index ${i} does not have a view.`); - } - this._addView(newItem); - } - } - get _selectedView(): View { let selectedIndex = this.selectedIndex; return selectedIndex > -1 ? this.items[selectedIndex].view : null; @@ -131,17 +100,21 @@ export class TabViewBase extends View implements TabViewDefinition, AddChildFrom return 0; } - public _eachChildView(callback: (child: ViewBase) => boolean) { + public eachChild(callback: (child: ViewBase) => boolean) { const items = this.items; - if (!items) { - return; - } - - for (let i = 0, length = items.length; i < length; i++) { - let item = items[i]; - if (item) { + if (items) { + items.forEach((item, i) => { callback(item); - } + }); + } + } + + public eachChildView(callback: (child: View) => boolean) { + const items = this.items; + if (items) { + items.forEach((item, i) => { + callback(item.view); + }); } } diff --git a/tns-core-modules/ui/tab-view/tab-view.android.ts b/tns-core-modules/ui/tab-view/tab-view.android.ts index 3fba3195b..0806994de 100644 --- a/tns-core-modules/ui/tab-view/tab-view.android.ts +++ b/tns-core-modules/ui/tab-view/tab-view.android.ts @@ -16,11 +16,11 @@ const PRIMARY_COLOR = "colorPrimary"; const DEFAULT_ELEVATION = 4; export class TabViewItem extends TabViewItemBase { - public _parent: TabView; public _update() { - if (this._parent) { - this._parent._updateTabForItem(this); + const parent = this.parent; + if (parent) { + parent._updateTabForItem(this); } } } @@ -62,9 +62,9 @@ function ensurePagerAdapterClass() { } let item = this.items[index]; - if (item.view.parent !== this.owner) { - this.owner._addView(item.view); - } + // if (item.view.parent !== this.owner) { + // this.owner._addView(item.view); + // } if (this[VIEWS_STATES]) { if (traceEnabled) { @@ -92,9 +92,9 @@ function ensurePagerAdapterClass() { // Note: this.owner._removeView will clear item.view._nativeView. // So call this after the native instance is removed form the container. - if (item.view.parent === this.owner) { - this.owner._removeView(item.view); - } + // if (item.view.parent === this.owner) { + // this.owner._removeView(item.view); + // } } isViewFromObject(view: android.view.View, _object: any) { @@ -122,7 +122,8 @@ function ensurePagerAdapterClass() { } return true; } - owner._eachChildView(childCallback); + + owner.eachChildView(childCallback); let bundle = new android.os.Bundle(); bundle.putSparseParcelableArray(VIEWS_STATES, viewStates); @@ -191,12 +192,12 @@ export class TabView extends TabViewBase { this.setElevation(); - let accentColor = ad.resources.getPalleteColor(ACCENT_COLOR, this._context); + const accentColor = ad.resources.getPalleteColor(ACCENT_COLOR, this._context); if (accentColor) { this._tabLayout.setSelectedIndicatorColors([accentColor]); } - let primaryColor = ad.resources.getPalleteColor(PRIMARY_COLOR, this._context); + const primaryColor = ad.resources.getPalleteColor(PRIMARY_COLOR, this._context); if (primaryColor) { this._tabLayout.setBackgroundColor(primaryColor); } @@ -207,7 +208,7 @@ export class TabView extends TabViewBase { this._viewPager = new android.support.v4.view.ViewPager(this._context); this._viewPager.setId(this._androidViewId); - let lp = new org.nativescript.widgets.CommonLayoutParams(); + const lp = new org.nativescript.widgets.CommonLayoutParams(); lp.row = 1; this._viewPager.setLayoutParams(lp); this._grid.addView(this._viewPager); @@ -218,7 +219,7 @@ export class TabView extends TabViewBase { } private setElevation() { - let compat = android.support.v4.view.ViewCompat; + const compat = android.support.v4.view.ViewCompat; if (compat.setElevation) { let val = DEFAULT_ELEVATION * layout.getDisplayDensity(); compat.setElevation(this._grid, val); @@ -226,48 +227,31 @@ export class TabView extends TabViewBase { } } - public _onItemsPropertyChangedSetNativeValue() { - throw new Error("Compilation error: Can't find this.previousItems"); - // let oldItems = this.previousItems; - // if (oldItems) { - // oldItems.forEach((oldItem) => { - // // _removeView is called within destroyItem method - // oldItem._parent = null; - // }); + private setAdapter(items: Array) { + const length = items ? items.length : 0; + if (length === 0) { + this._viewPager.setAdapter(null); + this._pagerAdapter = null; + this._tabLayout.setItems(null, null); + return; + } - // this._viewPager.setAdapter(null); - // this._pagerAdapter = null; - // this._tabLayout.setItems(null, null); - // } + const tabItems = new Array(); + items.forEach((item, idx, arr) => { + tabItems.push(this.createTabItem(item)); + }); - // let items = this.items; - // if (items) { - // let tabItems = new Array(); - // items.forEach((item, idx, arr) => { - // if (!item.view) { - // throw new Error("View of TabViewItem at index " + idx + " is " + item.view); - // } + ensurePagerAdapterClass(); + // TODO: optimize by reusing the adapter and calling setAdapter(null) then the same adapter. + this._pagerAdapter = new PagerAdapterClass(this, items); + this._viewPager.setAdapter(this._pagerAdapter); - // item._parent = this; - // if (item.view.parent !== this) { - // this._addView(item.view, idx); - // } - // tabItems.push(this.createTabItem(item)); - // }); + this._tabLayout.setItems(tabItems, this._viewPager); - // ensurePagerAdapterClass(); - // // TODO: optimize by reusing the adapter and calling setAdapter(null) then the same adapter. - // this._pagerAdapter = new PagerAdapterClass(this, items); - // this._viewPager.setAdapter(this._pagerAdapter); - - // this._tabLayout.setItems(tabItems, this._viewPager); - // } - - // let nativeSelectedIndex = this._viewPager.getCurrentItem(); - // let selectedIndex = this.selectedIndex; - // if (selectedIndex < 0) { - // this.selectedIndex = nativeSelectedIndex; - // } + let selectedIndex = this.selectedIndex; + if (selectedIndex < 0) { + this.selectedIndex = this._viewPager.getCurrentItem(); + } } public _updateTabForItem(item: TabViewItem) { @@ -320,7 +304,7 @@ export class TabView extends TabViewBase { return null; } set [itemsProperty.native](value: TabViewItemBase[]) { - this._onItemsPropertyChangedSetNativeValue(); + this.setAdapter(value); } get [tabTextColorProperty.native](): number { diff --git a/tns-core-modules/ui/tab-view/tab-view.ios.ts b/tns-core-modules/ui/tab-view/tab-view.ios.ts index 93832777a..f60c9cf08 100644 --- a/tns-core-modules/ui/tab-view/tab-view.ios.ts +++ b/tns-core-modules/ui/tab-view/tab-view.ios.ts @@ -121,23 +121,24 @@ function updateItemTitlePosition(tabBarItem: UITabBarItem): void { } export class TabViewItem extends TabViewItemBase { - public _controller: UIViewController; - public _parent: TabView; public _update() { - if (this._parent && this._controller) { - const icon = this._parent._getIcon(this.iconSource); - const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag((this.title), icon, this._parent.items.indexOf(this)); + const parent = this.parent; + let controller = this.nativeView; + if (parent && controller) { + const icon = parent._getIcon(this.iconSource); + const index = parent.items.indexOf(this); + const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(this.title, icon, index); if (!icon) { updateItemTitlePosition(tabBarItem); } // TODO: Repeating code. Make TabViewItemBase - ViewBase and move the colorProperty on tabViewItem. // Delete the repeating code. - const states = getTitleAttributesForStates(this._parent); + const states = getTitleAttributesForStates(parent); tabBarItem.setTitleTextAttributesForState(states.normalState, UIControlState.Normal); tabBarItem.setTitleTextAttributesForState(states.selectedState, UIControlState.Selected); - this._controller.tabBarItem = tabBarItem; + controller.tabBarItem = tabBarItem; } } } @@ -226,47 +227,30 @@ export class TabView extends TabViewBase { } } - public _removeTabs(oldItems: Array) { - if (traceEnabled) { - traceWrite("TabView._removeTabs(" + oldItems + ");", traceCategories.Debug); - } - super._removeTabs(oldItems); - - for (let i = 0, length = oldItems.length; i < length; i++) { - let oldItem = oldItems[i]; - oldItem._parent = null; - oldItem._controller = null; + private setViewControllers(items: Array) { + const length = items ? items.length : 0; + if (length === 0) { + this._ios.viewControllers = null; + return; } - this._ios.viewControllers = null; - } - - public _addTabs(newItems: Array) { - if (traceEnabled) { - traceWrite("TabView._addTabs(" + newItems + ");", traceCategories.Debug); - } - super._addTabs(newItems); - - const length = newItems.length; - const newControllers: NSMutableArray = NSMutableArray.alloc().initWithCapacity(length); + const controllers = NSMutableArray.alloc().initWithCapacity(length); const states = getTitleAttributesForStates(this); for (let i = 0; i < length; i++) { - const item = newItems[i]; + const item = items[i]; let newController: UIViewController; if (item.view.ios instanceof UIViewController) { - newController = item.view.ios; + newController = item.view.ios; } else { newController = UIViewController.new(); newController.view.addSubview(item.view.ios); } - item._parent = this; - item._controller = newController; + item.nativeView = newController; const icon = this._getIcon(item.iconSource); - const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag((item.title || ""), icon, i); if (!icon) { updateItemTitlePosition(tabBarItem); @@ -275,17 +259,17 @@ export class TabView extends TabViewBase { tabBarItem.setTitleTextAttributesForState(states.selectedState, UIControlState.Selected); newController.tabBarItem = tabBarItem; - newControllers.addObject(newController); + controllers.addObject(newController); } - this._ios.viewControllers = newControllers; + this._ios.viewControllers = controllers; this._ios.customizableViewControllers = null; // When we set this._ios.viewControllers, someone is clearing the moreNavigationController.delegate, so we have to reassign it each time here. this._ios.moreNavigationController.delegate = this._moreNavigationControllerDelegate; - if (this._ios.selectedIndex !== this.selectedIndex) { - this._ios.selectedIndex = this.selectedIndex; + if (this.selectedIndex < 0) { + this.selectedIndex = this._ios.selectedIndex; } } @@ -399,19 +383,6 @@ export class TabView extends TabViewBase { } } - private _onItemsPropertyChangedSetNativeValue() { - throw new Error("Compilation error: Can't find this.previousItems"); - // let oldValue = this.previousItems; - // if (oldValue) { - // this._removeTabs(oldValue); - // } - - // let newValue = this.items; - // if (newValue) { - // this._addTabs(newValue); - // } - } - get [selectedIndexProperty.native](): number { return -1; } @@ -429,7 +400,7 @@ export class TabView extends TabViewBase { return null; } set [itemsProperty.native](value: TabViewItemBase[]) { - this._onItemsPropertyChangedSetNativeValue(); + this.setViewControllers(value); } get [tabTextColorProperty.native](): UIColor { @@ -479,7 +450,7 @@ export class TabView extends TabViewBase { let items = this.items; if (items && items.length) { for (let i = 0, length = items.length; i < length; i++) { - const item = items[i]; + const item = items[i]; if (items[i].iconSource) { (items[i])._update(); } @@ -495,7 +466,7 @@ function getTitleAttributesForStates(tabView: TabView): { normalState: any, sele } const selectedState = {}; - let tabItemTextColor = tabView.style.tabTextColor; + let tabItemTextColor = tabView.style.tabTextColor; if (tabItemTextColor instanceof Color) { selectedState[UITextAttributeTextColor] = tabItemTextColor.ios; }