From cb4447275a556a692cc60ae2305e5310a9e49fae Mon Sep 17 00:00:00 2001 From: Martin Yankov Date: Thu, 25 Jul 2019 09:33:50 +0300 Subject: [PATCH 1/4] feat(tab): add support for no tabstrip --- .../custom-tabstrip-page.css | 31 ++++++++ .../bottom-navigation/custom-tabstrip-page.ts | 24 ++++++ .../custom-tabstrip-page.xml | 41 ++++++++++ .../app/bottom-navigation/main-page.ts | 1 + .../app/tabs/custom-tabstrip-page.css | 31 ++++++++ .../app/tabs/custom-tabstrip-page.ts | 24 ++++++ .../app/tabs/custom-tabstrip-page.xml | 41 ++++++++++ e2e/ui-tests-app/app/tabs/main-page.ts | 1 + .../bottom-navigation.e2e-spec.ts | 28 ++++++- .../tab-navigation-base-page.ts | 1 - .../tabs/tabs-tests.e2e-spec.ts | 26 +++++++ .../bottom-navigation.android.ts | 51 ++++++++----- .../bottom-navigation.ios.ts | 3 + tns-core-modules/ui/tabs/tabs.android.ts | 5 +- tns-core-modules/ui/tabs/tabs.ios.ts | 76 ++++++++++--------- 15 files changed, 324 insertions(+), 60 deletions(-) create mode 100644 e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.css create mode 100644 e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.ts create mode 100644 e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.xml create mode 100644 e2e/ui-tests-app/app/tabs/custom-tabstrip-page.css create mode 100644 e2e/ui-tests-app/app/tabs/custom-tabstrip-page.ts create mode 100644 e2e/ui-tests-app/app/tabs/custom-tabstrip-page.xml diff --git a/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.css b/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.css new file mode 100644 index 0000000000..0f7802b4de --- /dev/null +++ b/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.css @@ -0,0 +1,31 @@ +.custom-tabstrip { + height: 100; + vertical-align: bottom; + ios-overflow-safe-area-enabled: false; +} + +.custom-tabstripitem { + height: 80; + width: 80; + vertical-align: center; + horizontal-align: center; + clip-path: circle(100% at 50% 50%); +} + +.custom-title { + color: white; + vertical-align: center; + horizontal-align: center; +} + +.skyblue { + background-color: skyblue; +} + +.gold { + background-color: gold; +} + +.olive { + background-color: olive; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.ts b/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.ts new file mode 100644 index 0000000000..72a7615ce7 --- /dev/null +++ b/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.ts @@ -0,0 +1,24 @@ +import { EventData } from "tns-core-modules/data/observable"; +import { Page } from "tns-core-modules/ui/page"; +import { BottomNavigation } from "tns-core-modules/ui/bottom-navigation"; + +export function goToFirst(args: EventData) { + const page = (args.object).page; + const bottomNav = page.getViewById("bottomNav"); + + bottomNav.selectedIndex = 0; +} + +export function goToSecond(args: EventData) { + const page = (args.object).page; + const bottomNav = page.getViewById("bottomNav"); + + bottomNav.selectedIndex = 1; +} + +export function goToThird(args: EventData) { + const page = (args.object).page; + const bottomNav = page.getViewById("bottomNav"); + + bottomNav.selectedIndex = 2; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.xml b/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.xml new file mode 100644 index 0000000000..f5d923c724 --- /dev/null +++ b/e2e/ui-tests-app/app/bottom-navigation/custom-tabstrip-page.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/e2e/ui-tests-app/app/bottom-navigation/main-page.ts b/e2e/ui-tests-app/app/bottom-navigation/main-page.ts index f281c1e729..f3f6801afb 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/main-page.ts +++ b/e2e/ui-tests-app/app/bottom-navigation/main-page.ts @@ -23,6 +23,7 @@ export function loadExamples() { examples.set("font-icons", "bottom-navigation/font-icons-page"); examples.set("fancy-fonts", "bottom-navigation/fancy-fonts-page"); examples.set("css-text-transform", "bottom-navigation/bottom-navigation-css-page"); + examples.set("custom-tabstrip", "bottom-navigation/custom-tabstrip-page"); return examples; } diff --git a/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.css b/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.css new file mode 100644 index 0000000000..0f7802b4de --- /dev/null +++ b/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.css @@ -0,0 +1,31 @@ +.custom-tabstrip { + height: 100; + vertical-align: bottom; + ios-overflow-safe-area-enabled: false; +} + +.custom-tabstripitem { + height: 80; + width: 80; + vertical-align: center; + horizontal-align: center; + clip-path: circle(100% at 50% 50%); +} + +.custom-title { + color: white; + vertical-align: center; + horizontal-align: center; +} + +.skyblue { + background-color: skyblue; +} + +.gold { + background-color: gold; +} + +.olive { + background-color: olive; +} diff --git a/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.ts b/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.ts new file mode 100644 index 0000000000..258904ce7c --- /dev/null +++ b/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.ts @@ -0,0 +1,24 @@ +import { EventData } from "tns-core-modules/data/observable"; +import { Page } from "tns-core-modules/ui/page"; +import { Tabs } from "tns-core-modules/ui/tabs"; + +export function goToFirst(args: EventData) { + const page = (args.object).page; + const bottomNav = page.getViewById("tabsNav"); + + bottomNav.selectedIndex = 0; +} + +export function goToSecond(args: EventData) { + const page = (args.object).page; + const bottomNav = page.getViewById("tabsNav"); + + bottomNav.selectedIndex = 1; +} + +export function goToThird(args: EventData) { + const page = (args.object).page; + const bottomNav = page.getViewById("tabsNav"); + + bottomNav.selectedIndex = 2; +} diff --git a/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.xml b/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.xml new file mode 100644 index 0000000000..831d7f6d98 --- /dev/null +++ b/e2e/ui-tests-app/app/tabs/custom-tabstrip-page.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/main-page.ts b/e2e/ui-tests-app/app/tabs/main-page.ts index 17acc66e85..ec0632f91d 100644 --- a/e2e/ui-tests-app/app/tabs/main-page.ts +++ b/e2e/ui-tests-app/app/tabs/main-page.ts @@ -29,6 +29,7 @@ export function loadExamples() { examples.set("font-icons", "tabs/font-icons-page"); examples.set("nested-layout", "tabs/nested-layout-page"); examples.set("nested-bottom-navigation", "tabs/nested-bottom-navigation-page"); + examples.set("custom-tabstrip", "tabs/custom-tabstrip-page"); return examples; } diff --git a/e2e/ui-tests-app/e2e/suites/tab-navigation/bottom-navigation/bottom-navigation.e2e-spec.ts b/e2e/ui-tests-app/e2e/suites/tab-navigation/bottom-navigation/bottom-navigation.e2e-spec.ts index d6c537ff0b..3c27bc271c 100644 --- a/e2e/ui-tests-app/e2e/suites/tab-navigation/bottom-navigation/bottom-navigation.e2e-spec.ts +++ b/e2e/ui-tests-app/e2e/suites/tab-navigation/bottom-navigation/bottom-navigation.e2e-spec.ts @@ -40,6 +40,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-background-color`, async function () { await bottomNavigationBasePage.navigateToSample("background-color"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await bottomNavigationBasePage.tabOnItem(1); @@ -55,6 +56,7 @@ describe(`${suite}-${spec}-suite`, async function () { */ it(`${spec}-binding-add-items`, async function () { await bottomNavigationBasePage.navigateToSample("binding"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); const addTabBtn = await driver.waitForElement("add-tab"); @@ -83,6 +85,7 @@ describe(`${suite}-${spec}-suite`, async function () { */ it(`${spec}-binding-remove-items`, async function () { await bottomNavigationBasePage.navigateToSample("binding"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); const removeTabBtn = await driver.waitForElement("remove-last-tab"); @@ -115,6 +118,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-bottom-navigation`, async function () { await bottomNavigationBasePage.navigateToSample("bottom-navigation"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); const goToSecondBtn = await driver.waitForElement("goToSecond"); @@ -130,6 +134,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-color`, async function () { await bottomNavigationBasePage.navigateToSample("color"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await bottomNavigationBasePage.tabOnItem(1); @@ -141,6 +146,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-fancy-fonts-select-tabs`, async function () { await bottomNavigationBasePage.navigateToSample("fancy-fonts"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); for (let index = 1; index < 4; index++) { @@ -154,6 +160,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-fancy-fonts-selected-index`, async function () { await bottomNavigationBasePage.navigateToSample("fancy-fonts"); + await bottomNavigationBasePage.refreshTabItems(); let selectSecondTabFromCodeBehind = await driver.waitForElement("selectSecondTab"); logInfo(`Click on "select second tab button"`); @@ -186,7 +193,8 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-fancy-fonts-change-orientation`, async function () { await bottomNavigationBasePage.navigateToSample("fancy-fonts"); - await driver.setOrientation(DeviceOrientation.LANDSCAPE); + await bottomNavigationBasePage.refreshTabItems(); + await driver.setOrientation(DeviceOrientaion.LANDSCAPE); await driver.imageHelper.compareScreen(); await driver.backgroundApp(1); @@ -201,6 +209,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-font-icons`, async function () { await bottomNavigationBasePage.navigateToSample("font-icons"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await bottomNavigationBasePage.tabOnItem(1); @@ -216,6 +225,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-icon-change`, async function () { await bottomNavigationBasePage.navigateToSample("icon-change"); + await bottomNavigationBasePage.refreshTabItems(); await bottomNavigationBasePage.tabOnItem(1); await driver.imageHelper.compareScreen(); @@ -229,6 +239,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-icon-title-placment`, async function () { await bottomNavigationBasePage.navigateToSample("icon-title-placement"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); assert.isTrue(driver.imageHelper.hasImageComparisonPassed()); await bottomNavigationBasePage.navigateBackToSuitMainPage(); @@ -236,6 +247,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-5470-issue`, async function () { await bottomNavigationBasePage.navigateToSample("issue-5470"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await bottomNavigationBasePage.tabOnItem(1); @@ -247,6 +259,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-text-transform`, async function () { await bottomNavigationBasePage.navigateToSample("text-transform"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await bottomNavigationBasePage.tabOnItem(1); @@ -258,6 +271,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-fonts`, async function () { await bottomNavigationBasePage.navigateToSample("text-transform"); + await bottomNavigationBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await bottomNavigationBasePage.tabOnItem(1); @@ -266,4 +280,16 @@ describe(`${suite}-${spec}-suite`, async function () { assert.isTrue(driver.imageHelper.hasImageComparisonPassed()); await bottomNavigationBasePage.navigateBackToSuitMainPage(); }); + + it(`${spec}-custom-tabstrip`, async function () { + await bottomNavigationBasePage.navigateToSample("custom-tabstrip"); + await driver.imageHelper.compareScreen(); + + const secondTab = await driver.waitForElement("second-tab"); + await secondTab.tap(); + await driver.imageHelper.compareScreen(); + + assert.isTrue(driver.imageHelper.hasImageComparisonPassed()); + await bottomNavigationBasePage.navigateBackToSuitMainPage(); + }); }); \ No newline at end of file diff --git a/e2e/ui-tests-app/e2e/suites/tab-navigation/tab-navigation-base-page.ts b/e2e/ui-tests-app/e2e/suites/tab-navigation/tab-navigation-base-page.ts index 595fb2ebbd..1b483c377b 100644 --- a/e2e/ui-tests-app/e2e/suites/tab-navigation/tab-navigation-base-page.ts +++ b/e2e/ui-tests-app/e2e/suites/tab-navigation/tab-navigation-base-page.ts @@ -21,7 +21,6 @@ export abstract class TabNavigationBasePage extends PageObjectBaseModel { async navigateToSample(sample: string) { await super.navigateToSample(sample); - await this.refreshTabItems(); } async refreshTabItems() { diff --git a/e2e/ui-tests-app/e2e/suites/tab-navigation/tabs/tabs-tests.e2e-spec.ts b/e2e/ui-tests-app/e2e/suites/tab-navigation/tabs/tabs-tests.e2e-spec.ts index a889586b37..521aba3100 100644 --- a/e2e/ui-tests-app/e2e/suites/tab-navigation/tabs/tabs-tests.e2e-spec.ts +++ b/e2e/ui-tests-app/e2e/suites/tab-navigation/tabs/tabs-tests.e2e-spec.ts @@ -37,6 +37,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-background-color`, async function () { await tabsViewBasePage.navigateToSample("background-color"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await tabsViewBasePage.tabOnItem(1); @@ -50,6 +51,7 @@ describe(`${imagePrefix}-suite`, async function () { // not all css is applied. it(`${imagePrefix}-color`, async function () { await tabsViewBasePage.navigateToSample("color"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await tabsViewBasePage.tabOnItem(1); @@ -61,6 +63,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-font`, async function () { await tabsViewBasePage.navigateToSample("font"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await tabsViewBasePage.tabOnItem(1); @@ -76,6 +79,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-font-icons`, async function () { await tabsViewBasePage.navigateToSample("font-icons"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await tabsViewBasePage.tabOnItem(1); @@ -91,6 +95,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-highlight-color`, async function () { await tabsViewBasePage.navigateToSample("highlight-color"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await tabsViewBasePage.tabOnItem(1); @@ -103,6 +108,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-icon-change`, async function () { await tabsViewBasePage.navigateToSample("icon-change"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); @@ -119,6 +125,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-icon-title-placment`, async function () { await tabsViewBasePage.navigateToSample("icon-title-placement"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); assert.isTrue(driver.imageHelper.hasImageComparisonPassed()); await tabsViewBasePage.navigateBackToSuitMainPage(); @@ -126,6 +133,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-issue-5470`, async function () { await tabsViewBasePage.navigateToSample("issue-5470"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await tabsViewBasePage.tabOnItem(1); @@ -137,6 +145,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-strip-item`, async function () { await tabsViewBasePage.navigateToSample("strip-item"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); assert.isTrue(driver.imageHelper.hasImageComparisonPassed()); @@ -148,6 +157,7 @@ describe(`${imagePrefix}-suite`, async function () { this.skip(); } await tabsViewBasePage.navigateToSample("swipe-disabled"); + await tabsViewBasePage.refreshTabItems(); await tabsViewBasePage.swipeRightToLeft(); await driver.imageHelper.compareScreen(); @@ -159,6 +169,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-swipe`, async function () { await tabsViewBasePage.navigateToSample("tabs"); + await tabsViewBasePage.refreshTabItems(); await tabsViewBasePage.swipeRightToLeft(); await driver.imageHelper.compareScreen(); @@ -178,6 +189,7 @@ describe(`${imagePrefix}-suite`, async function () { this.skip(); } await tabsViewBasePage.navigateToSample("tabs-binding"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); const addTabBtn = await driver.waitForElement("add-tab"); @@ -209,6 +221,7 @@ describe(`${imagePrefix}-suite`, async function () { this.skip(); } await tabsViewBasePage.navigateToSample("tabs-binding"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); const removeTabBtn = await driver.waitForElement("remove-last-tab"); @@ -241,6 +254,7 @@ describe(`${imagePrefix}-suite`, async function () { it(`${imagePrefix}-text-transform`, async function () { await tabsViewBasePage.navigateToSample("text-transform"); + await tabsViewBasePage.refreshTabItems(); await driver.imageHelper.compareScreen(); await tabsViewBasePage.refreshTabItems(); @@ -250,4 +264,16 @@ describe(`${imagePrefix}-suite`, async function () { assert.isTrue(driver.imageHelper.hasImageComparisonPassed()); await tabsViewBasePage.navigateBackToSuitMainPage(); }); + + it(`${imagePrefix}-custom-tabstrip`, async function () { + await tabsViewBasePage.navigateToSample("custom-tabstrip"); + await driver.imageHelper.compareScreen(); + + const secondTab = await driver.waitForElement("second-tab"); + await secondTab.tap(); + await driver.imageHelper.compareScreen(); + + assert.isTrue(driver.imageHelper.hasImageComparisonPassed()); + await tabsViewBasePage.navigateBackToSuitMainPage(); + }); }); \ No newline at end of file diff --git a/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts b/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts index 18da53cffc..3ec37ad0b2 100644 --- a/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts +++ b/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts @@ -281,18 +281,20 @@ export class BottomNavigation extends TabNavigationBase { (nativeView).contentView = contentView; // TABSTRIP - const bottomNavigationBar = new BottomNavigationBar(context, this); - const bottomNavigationBarLayoutParams = new org.nativescript.widgets.CommonLayoutParams(); - bottomNavigationBarLayoutParams.row = 1; - bottomNavigationBar.setLayoutParams(bottomNavigationBarLayoutParams); - nativeView.addView(bottomNavigationBar); - (nativeView).bottomNavigationBar = bottomNavigationBar; - - setElevation(nativeView, bottomNavigationBar); - - const primaryColor = ad.resources.getPaletteColor(PRIMARY_COLOR, context); - if (primaryColor) { - bottomNavigationBar.setBackgroundColor(primaryColor); + if (this.tabStrip) { + const bottomNavigationBar = new BottomNavigationBar(context, this); + const bottomNavigationBarLayoutParams = new org.nativescript.widgets.CommonLayoutParams(); + bottomNavigationBarLayoutParams.row = 1; + bottomNavigationBar.setLayoutParams(bottomNavigationBarLayoutParams); + nativeView.addView(bottomNavigationBar); + (nativeView).bottomNavigationBar = bottomNavigationBar; + + setElevation(nativeView, bottomNavigationBar); + + const primaryColor = ad.resources.getPaletteColor(PRIMARY_COLOR, context); + if (primaryColor) { + bottomNavigationBar.setBackgroundColor(primaryColor); + } } return nativeView; @@ -313,10 +315,9 @@ export class BottomNavigation extends TabNavigationBase { this._contentView = (nativeView).contentView; this._contentView.setId(this._contentViewId); - this._bottomNavigationBar = (nativeView).bottomNavigationBar; - (this._bottomNavigationBar).owner = this; - if (this.tabStrip) { + this._bottomNavigationBar = (nativeView).bottomNavigationBar; + (this._bottomNavigationBar).owner = this; this.tabStrip.setNativeView(this._bottomNavigationBar); } } @@ -363,7 +364,9 @@ export class BottomNavigation extends TabNavigationBase { super.onLoaded(); const items = this.tabStrip ? this.tabStrip.items : null; - this.setTabStripItems(items); + if (this.tabStrip) { + this.setTabStripItems(items); + } if (this._attachedToWindow) { this.changeTab(this.selectedIndex); @@ -386,7 +389,9 @@ export class BottomNavigation extends TabNavigationBase { public onUnloaded(): void { super.onUnloaded(); - this.setTabStripItems(null); + if (this.tabStrip) { + this.setTabStripItems(null); + } const fragmentToDetach = this._currentFragment; if (fragmentToDetach) { @@ -396,8 +401,10 @@ export class BottomNavigation extends TabNavigationBase { } public disposeNativeView() { - this._bottomNavigationBar.setItems(null); - this._bottomNavigationBar = null; + if (this.tabStrip) { + this._bottomNavigationBar.setItems(null); + this._bottomNavigationBar = null; + } this.nativeViewProtected.removeOnAttachStateChangeListener(AttachStateChangeListener); this.nativeViewProtected[ownerSymbol] = null; @@ -637,7 +644,11 @@ export class BottomNavigation extends TabNavigationBase { // traceWrite("TabView this._viewPager.setCurrentItem(" + value + ", " + smoothScroll + ");", traceCategory); // } - this._bottomNavigationBar.setSelectedPosition(value); + if (this.tabStrip) { + this._bottomNavigationBar.setSelectedPosition(value); + } else { + this.changeTab(value); + } } [itemsProperty.getDefault](): TabContentItem[] { diff --git a/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts b/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts index 2cf65e877a..e3daa9470f 100644 --- a/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts +++ b/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts @@ -243,6 +243,9 @@ export class BottomNavigation extends TabNavigationBase { super.initNativeView(); this._delegate = UITabBarControllerDelegateImpl.initWithOwner(new WeakRef(this)); this._moreNavigationControllerDelegate = UINavigationControllerDelegateImpl.initWithOwner(new WeakRef(this)); + if (!this.tabStrip) { + this.viewController.tabBar.hidden = true; + } } disposeNativeView() { diff --git a/tns-core-modules/ui/tabs/tabs.android.ts b/tns-core-modules/ui/tabs/tabs.android.ts index 2b49932039..13b4571a79 100644 --- a/tns-core-modules/ui/tabs/tabs.android.ts +++ b/tns-core-modules/ui/tabs/tabs.android.ts @@ -493,7 +493,10 @@ export class Tabs extends TabsBase { super.onLoaded(); this.setItems((this.items)); - this.setTabStripItems(this.tabStrip.items); + + if (this.tabStrip) { + this.setTabStripItems(this.tabStrip.items); + } // this.setAdapterItems(this.items); } diff --git a/tns-core-modules/ui/tabs/tabs.ios.ts b/tns-core-modules/ui/tabs/tabs.ios.ts index f85baf6216..374854cb80 100644 --- a/tns-core-modules/ui/tabs/tabs.ios.ts +++ b/tns-core-modules/ui/tabs/tabs.ios.ts @@ -76,24 +76,27 @@ class UIPageViewControllerImpl extends UIPageViewController { public viewDidLoad(): void { const owner = this._owner.get(); - const tabBarItems = owner.tabBarItems; - const tabBar = MDCTabBar.alloc().initWithFrame(this.view.bounds); - if (tabBarItems && tabBarItems.length) { - tabBar.items = NSArray.arrayWithArray(tabBarItems); - } + if (owner.tabStrip) { + const tabBarItems = owner.tabBarItems; + const tabBar = MDCTabBar.alloc().initWithFrame(this.view.bounds); + + if (tabBarItems && tabBarItems.length) { + tabBar.items = NSArray.arrayWithArray(tabBarItems); + } - tabBar.delegate = this.tabBarDelegate = MDCTabBarDelegateImpl.initWithOwner(new WeakRef(owner)); - tabBar.tintColor = UIColor.blueColor; - tabBar.barTintColor = UIColor.whiteColor; - tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Normal); - tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Selected); - tabBar.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleBottomMargin; - tabBar.alignment = MDCTabBarAlignment.Leading; - tabBar.sizeToFit(); - - this.tabBar = tabBar; - this.view.addSubview(tabBar); + tabBar.delegate = this.tabBarDelegate = MDCTabBarDelegateImpl.initWithOwner(new WeakRef(owner)); + tabBar.tintColor = UIColor.blueColor; + tabBar.barTintColor = UIColor.whiteColor; + tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Normal); + tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Selected); + tabBar.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleBottomMargin; + tabBar.alignment = MDCTabBarAlignment.Leading; + tabBar.sizeToFit(); + + this.tabBar = tabBar; + this.view.addSubview(tabBar); + } } public viewWillAppear(animated: boolean): void { @@ -116,40 +119,39 @@ class UIPageViewControllerImpl extends UIPageViewController { return; } - const tabsPosition = owner.tabsPosition; - const parent = owner.parent; + let scrollViewTop = 0; + let scrollViewHeight = this.view.bounds.size.height + this.view.safeAreaInsets.bottom; - let tabBarTop = this.view.safeAreaInsets.top; - let tabBarHeight = this.tabBar.frame.size.height; - let scrollViewTop = this.tabBar.frame.size.height; - let scrollViewHeight = this.view.bounds.size.height - this.tabBar.frame.size.height; + if (owner.tabStrip) { + scrollViewTop = this.tabBar.frame.size.height; + scrollViewHeight = this.view.bounds.size.height - this.tabBar.frame.size.height + this.view.safeAreaInsets.bottom; + let tabBarTop = this.view.safeAreaInsets.top; + let tabBarHeight = this.tabBar.frame.size.height; - if (parent) { - // TODO: Figure out a better way to handle ViewController nesting/Safe Area nesting - tabBarTop = Math.max(this.view.safeAreaInsets.top, owner.parent.nativeView.safeAreaInsets.top); - } + const tabsPosition = owner.tabsPosition; + if (tabsPosition === "bottom") { + tabBarTop = this.view.frame.size.height - this.tabBar.frame.size.height - this.view.safeAreaInsets.bottom; + scrollViewTop = this.view.frame.origin.y; + scrollViewHeight = this.view.frame.size.height - this.view.safeAreaInsets.bottom; + } - if (tabsPosition === "bottom") { - tabBarTop = this.view.frame.size.height - this.tabBar.frame.size.height - this.view.safeAreaInsets.bottom; - scrollViewTop = this.view.frame.origin.y; - scrollViewHeight = this.view.frame.size.height - this.view.safeAreaInsets.bottom; - } + const parent = owner.parent; + if (parent) { + // TODO: Figure out a better way to handle ViewController nesting/Safe Area nesting + tabBarTop = Math.max(this.view.safeAreaInsets.top, owner.parent.nativeView.safeAreaInsets.top); + } - this.tabBar.frame = CGRectMake(this.view.safeAreaInsets.left, tabBarTop, this.tabBar.frame.size.width, tabBarHeight); + this.tabBar.frame = CGRectMake(this.view.safeAreaInsets.left, tabBarTop, this.tabBar.frame.size.width, tabBarHeight); + } const subViews: NSArray = this.view.subviews; let scrollView: UIScrollView = null; - let mdcBar: MDCTabBar = null; for (let i = 0; i < subViews.count; i++) { const view: UIView = subViews[i]; if (view instanceof UIScrollView) { scrollView = view; } - - if (view instanceof MDCTabBar) { - mdcBar = view; - } } if (scrollView) { From 552623146906155e2fd79ef716bba4d33ad2ca1f Mon Sep 17 00:00:00 2001 From: Martin Yankov Date: Mon, 12 Aug 2019 15:52:22 +0300 Subject: [PATCH 2/4] chore: fix typo --- .../bottom-navigation/bottom-navigation.e2e-spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/ui-tests-app/e2e/suites/tab-navigation/bottom-navigation/bottom-navigation.e2e-spec.ts b/e2e/ui-tests-app/e2e/suites/tab-navigation/bottom-navigation/bottom-navigation.e2e-spec.ts index 3c27bc271c..161f6ed606 100644 --- a/e2e/ui-tests-app/e2e/suites/tab-navigation/bottom-navigation/bottom-navigation.e2e-spec.ts +++ b/e2e/ui-tests-app/e2e/suites/tab-navigation/bottom-navigation/bottom-navigation.e2e-spec.ts @@ -194,7 +194,7 @@ describe(`${suite}-${spec}-suite`, async function () { it(`${spec}-fancy-fonts-change-orientation`, async function () { await bottomNavigationBasePage.navigateToSample("fancy-fonts"); await bottomNavigationBasePage.refreshTabItems(); - await driver.setOrientation(DeviceOrientaion.LANDSCAPE); + await driver.setOrientation(DeviceOrientation.LANDSCAPE); await driver.imageHelper.compareScreen(); await driver.backgroundApp(1); From 6fb15dbd85adaafd68bf30e0d61469fb05c74c29 Mon Sep 17 00:00:00 2001 From: Martin Yankov Date: Tue, 13 Aug 2019 13:05:04 +0300 Subject: [PATCH 3/4] wip: rework init lifecycles --- .../bottom-navigation-tests.ts | 2 + .../bottom-navigation.android.ts | 43 +++++++++---------- tns-core-modules/ui/tabs/tabs.ios.ts | 5 ++- 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/tests/app/ui/bottom-navigation/bottom-navigation-tests.ts b/tests/app/ui/bottom-navigation/bottom-navigation-tests.ts index ef07c7feb8..5678dbdcff 100644 --- a/tests/app/ui/bottom-navigation/bottom-navigation-tests.ts +++ b/tests/app/ui/bottom-navigation/bottom-navigation-tests.ts @@ -230,6 +230,7 @@ export class BottomNavigationTest extends UITest { public test_when_selecting_tab_natively_selectedIndex_is_updated_properly = function () { var tabView = this.testView; tabView.items = this._createContentItems(2); + tabView.tabStrip = this._createTabStrip(2); this.waitUntilTestElementIsLoaded(); var expectedValue = 1; @@ -245,6 +246,7 @@ export class BottomNavigationTest extends UITest { public test_when_selecting_tab_natively_selectedIndexChangedEvent_is_raised = function () { var tabView = this.testView; tabView.items = this._createContentItems(5); + tabView.tabStrip = this._createTabStrip(5); this.waitUntilTestElementIsLoaded(); var expectedOldIndex = 3; diff --git a/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts b/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts index 3ec37ad0b2..8cca2d108e 100644 --- a/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts +++ b/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts @@ -281,20 +281,18 @@ export class BottomNavigation extends TabNavigationBase { (nativeView).contentView = contentView; // TABSTRIP - if (this.tabStrip) { - const bottomNavigationBar = new BottomNavigationBar(context, this); - const bottomNavigationBarLayoutParams = new org.nativescript.widgets.CommonLayoutParams(); - bottomNavigationBarLayoutParams.row = 1; - bottomNavigationBar.setLayoutParams(bottomNavigationBarLayoutParams); - nativeView.addView(bottomNavigationBar); - (nativeView).bottomNavigationBar = bottomNavigationBar; - - setElevation(nativeView, bottomNavigationBar); - - const primaryColor = ad.resources.getPaletteColor(PRIMARY_COLOR, context); - if (primaryColor) { - bottomNavigationBar.setBackgroundColor(primaryColor); - } + const bottomNavigationBar = new BottomNavigationBar(context, this); + const bottomNavigationBarLayoutParams = new org.nativescript.widgets.CommonLayoutParams(); + bottomNavigationBarLayoutParams.row = 1; + bottomNavigationBar.setLayoutParams(bottomNavigationBarLayoutParams); + nativeView.addView(bottomNavigationBar); + (nativeView).bottomNavigationBar = bottomNavigationBar; + + setElevation(nativeView, bottomNavigationBar); + + const primaryColor = ad.resources.getPaletteColor(PRIMARY_COLOR, context); + if (primaryColor) { + bottomNavigationBar.setBackgroundColor(primaryColor); } return nativeView; @@ -315,9 +313,10 @@ export class BottomNavigation extends TabNavigationBase { this._contentView = (nativeView).contentView; this._contentView.setId(this._contentViewId); + this._bottomNavigationBar = (nativeView).bottomNavigationBar; + (this._bottomNavigationBar).owner = this; + if (this.tabStrip) { - this._bottomNavigationBar = (nativeView).bottomNavigationBar; - (this._bottomNavigationBar).owner = this; this.tabStrip.setNativeView(this._bottomNavigationBar); } } @@ -363,9 +362,11 @@ export class BottomNavigation extends TabNavigationBase { public onLoaded(): void { super.onLoaded(); - const items = this.tabStrip ? this.tabStrip.items : null; if (this.tabStrip) { - this.setTabStripItems(items); + this.setTabStripItems(this.tabStrip.items); + } else { + // manually set the visibility, so that the grid layout remeasures + this._bottomNavigationBar.setVisibility(android.view.View.GONE); } if (this._attachedToWindow) { @@ -401,10 +402,8 @@ export class BottomNavigation extends TabNavigationBase { } public disposeNativeView() { - if (this.tabStrip) { - this._bottomNavigationBar.setItems(null); - this._bottomNavigationBar = null; - } + this._bottomNavigationBar.setItems(null); + this._bottomNavigationBar = null; this.nativeViewProtected.removeOnAttachStateChangeListener(AttachStateChangeListener); this.nativeViewProtected[ownerSymbol] = null; diff --git a/tns-core-modules/ui/tabs/tabs.ios.ts b/tns-core-modules/ui/tabs/tabs.ios.ts index 374854cb80..a7a4928315 100644 --- a/tns-core-modules/ui/tabs/tabs.ios.ts +++ b/tns-core-modules/ui/tabs/tabs.ios.ts @@ -491,7 +491,10 @@ export class Tabs extends TabsBase { // this.viewController = this._ios = UIPageViewControllerImpl.initWithOwner(new WeakRef(this)); // .alloc().initWithTransitionStyleNavigationOrientationOptions(UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation.Horizontal, null); // UITabBarControllerImpl.initWithOwner(new WeakRef(this)); this.viewController = this._ios = UIPageViewControllerImpl.initWithOwner(new WeakRef(this)); //alloc().initWithTransitionStyleNavigationOrientationOptions(UIPageViewControllerTransitionStyle.Scroll, UIPageViewControllerNavigationOrientation.Horizontal, null);; - this.nativeViewProtected = this._ios.view; + } + + createNativeView() { + return this._ios.view; } initNativeView() { From 3ea161fe75bc431c298507af6b3e793343fdb7f9 Mon Sep 17 00:00:00 2001 From: Martin Yankov Date: Wed, 14 Aug 2019 16:23:21 +0300 Subject: [PATCH 4/4] fix: incorrect top tab bar coordinates --- tns-core-modules/ui/tabs/tabs.ios.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tns-core-modules/ui/tabs/tabs.ios.ts b/tns-core-modules/ui/tabs/tabs.ios.ts index a7a4928315..0fa5805d70 100644 --- a/tns-core-modules/ui/tabs/tabs.ios.ts +++ b/tns-core-modules/ui/tabs/tabs.ios.ts @@ -138,7 +138,7 @@ class UIPageViewControllerImpl extends UIPageViewController { const parent = owner.parent; if (parent) { // TODO: Figure out a better way to handle ViewController nesting/Safe Area nesting - tabBarTop = Math.max(this.view.safeAreaInsets.top, owner.parent.nativeView.safeAreaInsets.top); + tabBarTop = Math.max(tabBarTop, owner.parent.nativeView.safeAreaInsets.top); } this.tabBar.frame = CGRectMake(this.view.safeAreaInsets.left, tabBarTop, this.tabBar.frame.size.width, tabBarHeight);