Skip to content

Commit 89fb903

Browse files
committed
fix: fixes for bottom-navigation and tabs
1 parent ea44b7e commit 89fb903

File tree

20 files changed

+406
-260
lines changed

20 files changed

+406
-260
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { Directive, NgModule } from '@angular/core';
2+
import { registerElement } from '@nativescript/angular';
3+
import { BottomNavigation } from '@nativescript-community/ui-material-bottomnavigation';
4+
5+
@Directive({ selector: 'MDBottomNavigation' })
6+
export class MaterialBottomNavigationDirective {}
7+
8+
@NgModule({
9+
declarations: [MaterialBottomNavigationDirective],
10+
exports: [MaterialBottomNavigationDirective]
11+
})
12+
export class NativeScriptMaterialBottomNavigationModule {}
13+
14+
registerElement('MDBottomNavigation', () => BottomNavigation);
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"name": "@nativescript-community/ui-material-bottomnavigation-angular",
3+
"main": "index.js",
4+
"ngPackage": {
5+
"dest":"../../../packages/bottomnavigation/angular",
6+
"lib": {
7+
"entryFile": "index.ts",
8+
"umdModuleIds": {
9+
"@nativescript/core": "ns-core",
10+
"@nativescript/angular": "ns-angular",
11+
"@nativescript-community/ui-material-bottomnavigation": "ns-material-bottomnavigation"
12+
}
13+
},
14+
"whitelistedNonPeerDependencies": [
15+
"."
16+
]
17+
}
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"extends": "../../../tsconfig.json",
3+
"compilerOptions": {
4+
"rootDir": "./",
5+
"paths": {
6+
"tns-core-modules": ["./node_modules/@nativescript/core"],
7+
"tns-core-modules/*": ["./node_modules/@nativescript/core/*"],
8+
"@nativescript-community/ui-material-core": ["packages/core/index"],
9+
"@nativescript-community/ui-material-core/*": ["packages/core/*"],
10+
"@nativescript-community/ui-material-bottomnavigation": ["packages/bottomnavigation/index"],
11+
"@nativescript-community/ui-material-bottomnavigation/*": ["packages/bottomnavigation/*"]
12+
}
13+
},
14+
"include": ["./**/*.ts", "../../../references.d.ts", "../../references.d.ts"],
15+
"angularCompilerOptions": {
16+
"enableIvy": true
17+
}
18+
}

src/bottom-navigation/index.android.ts

Lines changed: 84 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { TabStripItem } from '@nativescript-community/ui-material-core/tab-navig
66
// Requires
77
import { Application, CSSType, Color, Font, Frame, ImageSource, Utils, View, getIconSpecSize } from '@nativescript/core';
88
import { TextTransform, getTransformedText } from '@nativescript/core/ui/text-base';
9+
export { TabContentItem, TabStrip, TabStripItem };
910

1011
// TODO: Impl trace
1112
// import { Trace } from "../../../trace";
@@ -344,19 +345,21 @@ export class BottomNavigation extends TabNavigationBase {
344345

345346
iterateIndexRange(newIndex, offsideItems, lastIndex, (i) => toLoad.push(i));
346347

347-
items.forEach((item, i) => {
348-
const indexOfI = toLoad.indexOf(i);
349-
if (indexOfI < 0) {
350-
toUnload.push(i);
351-
}
352-
});
348+
if (this.unloadOnTabChange) {
349+
items.forEach((item, i) => {
350+
const indexOfI = toLoad.indexOf(i);
351+
if (indexOfI < 0) {
352+
toUnload.push(i);
353+
}
354+
});
353355

354-
toUnload.forEach((index) => {
355-
const item = items[index];
356-
if (items[index]) {
357-
item.unloadView(item.content);
358-
}
359-
});
356+
toUnload.forEach((index) => {
357+
const item = items[index];
358+
if (items[index]) {
359+
item.unloadView(item.content);
360+
}
361+
});
362+
}
360363

361364
const newItem = items[newIndex];
362365
const selectedView = newItem && newItem.content;
@@ -417,11 +420,10 @@ export class BottomNavigation extends TabNavigationBase {
417420
this.setTabStripItems(null);
418421
}
419422

420-
const fragmentToDetach = this._currentFragment;
421-
if (fragmentToDetach) {
422-
this.destroyItem((fragmentToDetach as any).index, fragmentToDetach);
423-
this.removeFragment(fragmentToDetach);
424-
}
423+
this.items.forEach((item, i) => {
424+
item.unloadView(item.content);
425+
});
426+
this.disposeTabFragments();
425427
}
426428

427429
public disposeNativeView() {
@@ -495,7 +497,12 @@ export class BottomNavigation extends TabNavigationBase {
495497

496498
const fragmentToDetach = this._currentFragment;
497499
if (fragmentToDetach) {
498-
this.destroyItem((fragmentToDetach as any).index, fragmentToDetach);
500+
console.log('unloadOnTabChange', this.unloadOnTabChange);
501+
if (this.unloadOnTabChange) {
502+
this.destroyItem((fragmentToDetach as any).index, fragmentToDetach);
503+
} else {
504+
this.hideFragment(fragmentToDetach as any);
505+
}
499506
}
500507

501508
const fragment = this.instantiateItem(this._contentView, index);
@@ -532,6 +539,9 @@ export class BottomNavigation extends TabNavigationBase {
532539
if (fragment != null) {
533540
fragment.setMenuVisibility(true);
534541
fragment.setUserVisibleHint(true);
542+
if (!this.unloadOnTabChange) {
543+
this.showFragment(fragment);
544+
}
535545
}
536546

537547
this._currentFragment = fragment;
@@ -545,19 +555,73 @@ export class BottomNavigation extends TabNavigationBase {
545555
}
546556
}
547557
}
548-
549558
private destroyItem(position: number, fragment: androidx.fragment.app.Fragment): void {
550559
if (fragment) {
551560
this.removeFragment(fragment);
552561
if (this._currentFragment === fragment) {
553562
this._currentFragment = null;
554563
}
555564
}
556-
557565
if (this.items && this.items[position]) {
558566
this.items[position].canBeLoaded = false;
559567
}
560568
}
569+
private hideFragment(fragment: androidx.fragment.app.Fragment, fragmentManager?: any) {
570+
if (!fragmentManager) {
571+
fragmentManager = this._getFragmentManager();
572+
}
573+
if (fragment) {
574+
if (!fragment.isAdded() || fragment.isRemoving()) {
575+
// ignore
576+
return;
577+
} else {
578+
const fragmentExitTransition = fragment.getExitTransition();
579+
if (fragmentExitTransition && fragmentExitTransition instanceof org.nativescript.widgets.CustomTransition) {
580+
fragmentExitTransition.setResetOnTransitionEnd(true);
581+
}
582+
if (fragment && fragment.isAdded() && !fragment.isRemoving()) {
583+
const pfm = (fragment as any).getParentFragmentManager ? (fragment as any).getParentFragmentManager() : null;
584+
if (pfm && !pfm.isDestroyed()) {
585+
try {
586+
if (pfm.isStateSaved()) {
587+
pfm.beginTransaction().hide(fragment).commitNowAllowingStateLoss();
588+
} else {
589+
pfm.beginTransaction().hide(fragment).commitNow();
590+
}
591+
} catch (e) {}
592+
}
593+
}
594+
}
595+
}
596+
}
597+
private showFragment(fragment: androidx.fragment.app.Fragment, fragmentManager?: any) {
598+
if (!fragmentManager) {
599+
fragmentManager = this._getFragmentManager();
600+
}
601+
if (fragment) {
602+
if (!fragment.isAdded() || fragment.isRemoving()) {
603+
// ignore
604+
return;
605+
} else {
606+
const fragmentExitTransition = fragment.getExitTransition();
607+
if (fragmentExitTransition && fragmentExitTransition instanceof org.nativescript.widgets.CustomTransition) {
608+
fragmentExitTransition.setResetOnTransitionEnd(true);
609+
}
610+
if (fragment && fragment.isAdded() && !fragment.isRemoving()) {
611+
const pfm = (fragment as any).getParentFragmentManager ? (fragment as any).getParentFragmentManager() : null;
612+
if (pfm && !pfm.isDestroyed()) {
613+
try {
614+
if (pfm.isStateSaved()) {
615+
pfm.beginTransaction().show(fragment).commitNowAllowingStateLoss();
616+
} else {
617+
pfm.beginTransaction().show(fragment).commitNow();
618+
}
619+
} catch (e) {}
620+
}
621+
}
622+
}
623+
}
624+
}
561625
private removeFragment(fragment: androidx.fragment.app.Fragment, fragmentManager?: any) {
562626
if (!fragmentManager) {
563627
fragmentManager = this._getFragmentManager();

src/bottom-navigation/index.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22
import { TabNavigationBase } from '@nativescript-community/ui-material-core/tab-navigation-base/tab-navigation-base';
33
import { TabStrip } from '@nativescript-community/ui-material-core/tab-navigation-base/tab-strip';
44
import { CoercibleProperty, EventData, Property } from '@nativescript/core';
5+
import { TabStripItem } from '@nativescript-community/ui-material-core/tab-navigation-base/tab-strip-item';
56

7+
export { TabContentItem, TabStrip, TabStripItem };
68
/**
79
* Defines the data for the TabView.selectedIndexChanged event.
810
*/

src/bottom-navigation/index.ios.ts

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ import { TabStrip } from '@nativescript-community/ui-material-core/tab-navigatio
55
import { TabStripItem } from '@nativescript-community/ui-material-core/tab-navigation-base/tab-strip-item';
66
// Types
77
// Requires
8-
import { Application, CSSType, Color, Device, Font, Frame, IOSHelper, ImageSource, Utils, View, getIconSpecSize } from '@nativescript/core';
8+
import { CSSType, Color, Device, Font, Frame, IOSHelper, ImageSource, Utils, View, getIconSpecSize } from '@nativescript/core';
99
import { TextTransform, getTransformedText } from '@nativescript/core/ui/text-base';
1010
import { iOSNativeHelper } from '@nativescript/core/utils';
11+
export { TabContentItem, TabStrip, TabStripItem };
1112

1213
// TODO:
1314
// import { profile } from "../../profiling";
@@ -79,10 +80,14 @@ class UITabBarControllerImpl extends UITabBarController {
7980

8081
if (majorVersion >= 13) {
8182
const owner = this._owner.get();
82-
if (owner && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection && this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection(previousTraitCollection)) {
83+
if (
84+
owner &&
85+
this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection &&
86+
this.traitCollection.hasDifferentColorAppearanceComparedToTraitCollection(previousTraitCollection)
87+
) {
8388
owner.notify({
8489
eventName: IOSHelper.traitCollectionColorAppearanceChangedEvent,
85-
object: owner,
90+
object: owner
8691
});
8792
}
8893
}
@@ -125,7 +130,7 @@ class UITabBarControllerDelegateImpl extends NSObject implements UITabBarControl
125130
tabStrip.notify({
126131
eventName: TabStrip.itemTapEvent,
127132
object: tabStrip,
128-
index: position,
133+
index: position
129134
});
130135
}
131136
}
@@ -230,7 +235,7 @@ function updateTitleAndIconPositions(tabStripItem: TabStripItem, tabBarItem: UIT
230235
if (isIconAboveTitle) {
231236
tabBarItem.titlePositionAdjustment = {
232237
horizontal: 0,
233-
vertical: -20,
238+
vertical: -20
234239
};
235240
} else {
236241
tabBarItem.titlePositionAdjustment = { horizontal: 0, vertical: 0 };
@@ -243,14 +248,14 @@ function updateTitleAndIconPositions(tabStripItem: TabStripItem, tabBarItem: UIT
243248
top: 6,
244249
left: 0,
245250
bottom: -6,
246-
right: 0,
251+
right: 0
247252
});
248253
} else {
249254
tabBarItem.imageInsets = new UIEdgeInsets({
250255
top: 0,
251256
left: 0,
252257
bottom: 0,
253-
right: 0,
258+
right: 0
254259
});
255260
}
256261
}
@@ -303,14 +308,19 @@ export class BottomNavigation extends TabNavigationBase {
303308
}
304309

305310
this._ios.delegate = this._delegate;
311+
this.onSelectedIndexChanged(selectedIndex, selectedIndex);
306312
}
307313

308314
public onUnloaded() {
309315
this._ios.delegate = null;
310316
this._ios.moreNavigationController.delegate = null;
311317
super.onUnloaded();
318+
this.items.forEach((item, i) => {
319+
item.unloadView(item.content);
320+
});
312321
}
313322

323+
// @ts-ignore
314324
get ios(): UITabBarController {
315325
return this._ios;
316326
}
@@ -328,11 +338,12 @@ export class BottomNavigation extends TabNavigationBase {
328338
if (!items) {
329339
return;
330340
}
331-
332-
const oldItem = items[oldIndex];
333-
if (oldItem) {
334-
oldItem.canBeLoaded = false;
335-
oldItem.unloadView(oldItem.content);
341+
if (this.unloadOnTabChange) {
342+
const oldItem = items[oldIndex];
343+
if (oldItem) {
344+
oldItem.canBeLoaded = false;
345+
oldItem.unloadView(oldItem.content);
346+
}
336347
}
337348

338349
const newItem = items[newIndex];
@@ -704,7 +715,7 @@ export class BottomNavigation extends TabNavigationBase {
704715

705716
const iconSpecSize = getIconSpecSize({
706717
width: inWidth,
707-
height: inHeight,
718+
height: inHeight
708719
});
709720

710721
const widthPts = iconSpecSize.width;
@@ -743,7 +754,6 @@ export class BottomNavigation extends TabNavigationBase {
743754
// if (Trace.isEnabled()) {
744755
// Trace.write("TabView._onSelectedIndexPropertyChangedSetNativeValue(" + value + ")", Trace.categories.Debug);
745756
// }
746-
747757
if (value > -1) {
748758
(this._ios as any)._willSelectViewController = this._ios.viewControllers[value];
749759
this._ios.selectedIndex = value;
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
export default {
2+
model: {
3+
prop: 'selectedIndex',
4+
event: 'selectedIndexChange'
5+
},
6+
7+
render(h) {
8+
return h(
9+
'NativeMDBottomNavigation',
10+
{
11+
on: this.$listeners,
12+
attrs: this.$attrs
13+
},
14+
this.$slots.default
15+
);
16+
},
17+
18+
methods: {
19+
registerTabStrip(tabStrip) {
20+
this.$el.setAttribute('tabStrip', tabStrip);
21+
},
22+
registerTabContentItem(tabContentItem) {
23+
const items = this.$el.nativeView.items || [];
24+
25+
this.$el.setAttribute('items', items.concat([tabContentItem]));
26+
}
27+
}
28+
};

src/bottom-navigation/vue/index.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { BottomNavigation, TabContentItem, TabStrip, TabStripItem } from '../';
2+
3+
let installed = false;
4+
5+
export default {
6+
install(Vue) {
7+
if (!installed) {
8+
installed = true;
9+
Vue.registerElement('MDBottomNavigation', () => BottomNavigation, {
10+
model: {
11+
prop: 'selectedIndex',
12+
event: 'selectedIndexChange'
13+
},
14+
component: require('./component').default
15+
});
16+
Vue.registerElement('MDTabContentItem', () => TabContentItem, {});
17+
Vue.registerElement('MDTabStripItem', () => TabStripItem, {});
18+
Vue.registerElement('MDTabStrip', () => TabStrip, {});
19+
}
20+
}
21+
};

src/core/tab-navigation-base/tab-content-item/tab-content-item-common.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { TabNavigationBase } from '../tab-navigation-base';
55

66
export const traceCategory = 'TabView';
77

8-
@CSSType('TabContentItem')
8+
@CSSType('MDTabContentItem')
99
export abstract class TabContentItemBase extends ContentView implements TabContentItemDefinition, AddChildFromBuilder {
1010
public eachChild(callback: (child: View) => boolean) {
1111
if (this.content) {

0 commit comments

Comments
 (0)