diff --git a/CHANGELOG.md b/CHANGELOG.md index 75e92afc2..9c7ea49ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -89,7 +89,7 @@ Use `AndroidApplication.startActivity`, `AndroidApplication.foregroundActivity`, * `start(...)` method in `tns-core-modules/application` module is now removed. -Use `application.run(...)` method instead. +Use `application.run(...)` method instead. Check the "Flexible Frame Composition" section in [this document](https://docs.google.com/document/d/1Iia0yEr5seq4H9qk4oMuJs4-M8dgmne98fymCO5IczA/edit) that explains the full migration path from `application.start(...)` to `application.run(...)` and the implications from this change * `loadPage(...)` method in `tns-core-modules/ui/builder` module is now removed. diff --git a/e2e/ui-tests-app/app/bottom-navigation/bottom-navigation-view-model.ts b/e2e/ui-tests-app/app/bottom-navigation/bottom-navigation-view-model.ts index f4f699e5e..464f1dec0 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/bottom-navigation-view-model.ts +++ b/e2e/ui-tests-app/app/bottom-navigation/bottom-navigation-view-model.ts @@ -52,7 +52,7 @@ export class BottomNavigationViewModel extends Observable { const gridlayout = new GridLayout(); label.text = "Content Item " + index; gridlayout.addChild(label); - contentItem.view = gridlayout; + contentItem.content = gridlayout; return contentItem; } diff --git a/e2e/ui-tests-app/app/bottom-navigation/color-page.css b/e2e/ui-tests-app/app/bottom-navigation/color-page.css index 17d688073..3b7744d0d 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/color-page.css +++ b/e2e/ui-tests-app/app/bottom-navigation/color-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { color: yellowgreen; } + +TabStripItem.nested Label { + color: teal; +} + +TabStripItem.nested:active Label { + color: yellowgreen; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/color-page.xml b/e2e/ui-tests-app/app/bottom-navigation/color-page.xml index b8c3e9d4e..b63d6c8c4 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/color-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/color-page.xml @@ -3,10 +3,13 @@ - + - - + + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css b/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css index ee183523d..57076da81 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css +++ b/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.css @@ -6,6 +6,34 @@ font-size: 36; } -.color { - color: blue; -} \ No newline at end of file +TabStrip { + color: mediumvioletred; +} + +TabStripItem { + color: skyblue; +} + +TabStripItem:active { + color: darkblue; +} + +TabStripItem.special Image { + color: lightgreen; +} + +TabStripItem.special:active Image { + color: darkgreen; +} + +TabStripItem.special Label { + color: gold; +} + +TabStripItem.special:active Label { + color: darkgoldenrod; +} + +TabStripItem:active .font-size { + font-size: 10; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml b/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml index 644cdb121..c72f3320f 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/font-icons-page.xml @@ -3,32 +3,61 @@ - + - - + + + + - + + + - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/bottom-navigation/font-page.css b/e2e/ui-tests-app/app/bottom-navigation/font-page.css index 22a3ce46c..57b0eda89 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/font-page.css +++ b/e2e/ui-tests-app/app/bottom-navigation/font-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { font: 16 monospace; } + +TabStripItem.nested Label { + font: 12 monospace; +} + +TabStripItem.nested:active Label { + font: 16 monospace; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/font-page.xml b/e2e/ui-tests-app/app/bottom-navigation/font-page.xml index 6da1c6233..b59f818d8 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/font-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/font-page.xml @@ -1,12 +1,15 @@ - + - + - - + + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.ts b/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.ts index 199c5c566..bfb016431 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.ts +++ b/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.ts @@ -6,10 +6,12 @@ export function onSelectedIndexChanged(args: SelectedIndexChangedEventData) { const newItem = bottomNav.tabStrip.items[args.newIndex]; if (newItem) { newItem.iconSource = "res://icon"; + newItem.title = "selected"; } const oldItem = bottomNav.tabStrip.items[args.oldIndex]; if (oldItem) { oldItem.iconSource = "res://testlogo"; + oldItem.title = "unselected"; } } diff --git a/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.xml b/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.xml index 40bf3afac..1305f2a06 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/icon-change-page.xml @@ -4,8 +4,8 @@ - - + + diff --git a/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.css b/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.css index 80b3649d4..539c8c817 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.css +++ b/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { text-transform: uppercase; } + +TabStripItem.nested Label { + text-transform: lowercase; +} + +TabStripItem.nested:active Label { + text-transform: uppercase; +} diff --git a/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.xml b/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.xml index 33db487c6..dcddb8bd6 100644 --- a/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.xml +++ b/e2e/ui-tests-app/app/bottom-navigation/text-transform-page.xml @@ -1,12 +1,15 @@ - + - + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/color-page.css b/e2e/ui-tests-app/app/tabs/color-page.css index b417cfecf..97c0d950b 100644 --- a/e2e/ui-tests-app/app/tabs/color-page.css +++ b/e2e/ui-tests-app/app/tabs/color-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { color: yellowgreen; } + +TabStripItem.nested Label { + color: teal; +} + +TabStripItem.nested:active Label { + color: yellowgreen; +} diff --git a/e2e/ui-tests-app/app/tabs/color-page.xml b/e2e/ui-tests-app/app/tabs/color-page.xml index be732a6c3..5741956f5 100644 --- a/e2e/ui-tests-app/app/tabs/color-page.xml +++ b/e2e/ui-tests-app/app/tabs/color-page.xml @@ -1,12 +1,15 @@ - + - + - - + + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/font-icons-page.css b/e2e/ui-tests-app/app/tabs/font-icons-page.css index ee183523d..57076da81 100644 --- a/e2e/ui-tests-app/app/tabs/font-icons-page.css +++ b/e2e/ui-tests-app/app/tabs/font-icons-page.css @@ -6,6 +6,34 @@ font-size: 36; } -.color { - color: blue; -} \ No newline at end of file +TabStrip { + color: mediumvioletred; +} + +TabStripItem { + color: skyblue; +} + +TabStripItem:active { + color: darkblue; +} + +TabStripItem.special Image { + color: lightgreen; +} + +TabStripItem.special:active Image { + color: darkgreen; +} + +TabStripItem.special Label { + color: gold; +} + +TabStripItem.special:active Label { + color: darkgoldenrod; +} + +TabStripItem:active .font-size { + font-size: 10; +} diff --git a/e2e/ui-tests-app/app/tabs/font-icons-page.xml b/e2e/ui-tests-app/app/tabs/font-icons-page.xml index 317d5def4..0a31a8d76 100644 --- a/e2e/ui-tests-app/app/tabs/font-icons-page.xml +++ b/e2e/ui-tests-app/app/tabs/font-icons-page.xml @@ -3,32 +3,61 @@ - + - - + + + + - + + + - + + - - + + - - + + - - + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/font-page.css b/e2e/ui-tests-app/app/tabs/font-page.css index 1e28cb2a5..d2473e4d7 100644 --- a/e2e/ui-tests-app/app/tabs/font-page.css +++ b/e2e/ui-tests-app/app/tabs/font-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { font: 16 monospace; } + +TabStripItem.nested Label { + font: 12 monospace; +} + +TabStripItem.nested:active Label { + font: 16 monospace; +} diff --git a/e2e/ui-tests-app/app/tabs/font-page.xml b/e2e/ui-tests-app/app/tabs/font-page.xml index a0c8bfa60..ee9003d98 100644 --- a/e2e/ui-tests-app/app/tabs/font-page.xml +++ b/e2e/ui-tests-app/app/tabs/font-page.xml @@ -1,12 +1,15 @@ - + - - + + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/e2e/ui-tests-app/app/tabs/icon-change-page.ts b/e2e/ui-tests-app/app/tabs/icon-change-page.ts index 1a466d6a6..cf4e24af1 100644 --- a/e2e/ui-tests-app/app/tabs/icon-change-page.ts +++ b/e2e/ui-tests-app/app/tabs/icon-change-page.ts @@ -6,10 +6,12 @@ export function onSelectedIndexChanged(args: SelectedIndexChangedEventData) { const newItem = tabsNav.tabStrip.items[args.newIndex]; if (newItem) { newItem.iconSource = "res://icon"; + newItem.title = "selected"; } const oldItem = tabsNav.tabStrip.items[args.oldIndex]; if (oldItem) { oldItem.iconSource = "res://testlogo"; + oldItem.title = "unselected"; } } diff --git a/e2e/ui-tests-app/app/tabs/icon-change-page.xml b/e2e/ui-tests-app/app/tabs/icon-change-page.xml index 28f78dc9f..9dc1ede30 100644 --- a/e2e/ui-tests-app/app/tabs/icon-change-page.xml +++ b/e2e/ui-tests-app/app/tabs/icon-change-page.xml @@ -4,8 +4,8 @@ - - + + diff --git a/e2e/ui-tests-app/app/tabs/tabs-binding-view-model.ts b/e2e/ui-tests-app/app/tabs/tabs-binding-view-model.ts index 18a51c893..531961775 100644 --- a/e2e/ui-tests-app/app/tabs/tabs-binding-view-model.ts +++ b/e2e/ui-tests-app/app/tabs/tabs-binding-view-model.ts @@ -53,7 +53,7 @@ export class TabsBindingNavigationViewModel extends Observable { const gridlayout = new GridLayout(); label.text = "Content Item " + index; gridlayout.addChild(label); - contentItem.view = gridlayout; + contentItem.content = gridlayout; return contentItem; } diff --git a/e2e/ui-tests-app/app/tabs/text-transform-page.css b/e2e/ui-tests-app/app/tabs/text-transform-page.css index db5fd0e50..ebbc005bd 100644 --- a/e2e/ui-tests-app/app/tabs/text-transform-page.css +++ b/e2e/ui-tests-app/app/tabs/text-transform-page.css @@ -17,3 +17,11 @@ TabStripItem.special { TabStripItem.special:active { text-transform: uppercase; } + +TabStripItem.nested Label { + text-transform: lowercase; +} + +TabStripItem.nested:active Label { + text-transform: uppercase; +} diff --git a/e2e/ui-tests-app/app/tabs/text-transform-page.xml b/e2e/ui-tests-app/app/tabs/text-transform-page.xml index c80979319..aa9ea5bf3 100644 --- a/e2e/ui-tests-app/app/tabs/text-transform-page.xml +++ b/e2e/ui-tests-app/app/tabs/text-transform-page.xml @@ -1,12 +1,15 @@ - + - + + + @@ -20,5 +23,11 @@ + + + + + \ No newline at end of file diff --git a/tests/app/ui/bottom-navigation/bottom-navigation-navigation-tests.ts b/tests/app/ui/bottom-navigation/bottom-navigation-navigation-tests.ts index c1ed2b09c..a72d3e2e6 100644 --- a/tests/app/ui/bottom-navigation/bottom-navigation-navigation-tests.ts +++ b/tests/app/ui/bottom-navigation/bottom-navigation-navigation-tests.ts @@ -23,7 +23,7 @@ function _createContentItems(count: number): Array { const label = new Label(); label.text = "Tab " + i; const tabEntry = new TabContentItem(); - tabEntry.view = label; + tabEntry.content = label; items.push(tabEntry); } @@ -101,12 +101,12 @@ export function testBackNavigationToTabViewWithNestedFramesShouldWork() { let items = Array(); let tabViewitem = new TabContentItem(); // tabViewitem.title = "Item1"; - tabViewitem.view = _createFrameView(); + tabViewitem.content = _createFrameView(); items.push(tabViewitem); let tabViewitem2 = new TabContentItem(); // tabViewitem2.title = "Item2"; - tabViewitem2.view = _createFrameView(); + tabViewitem2.content = _createFrameView(); items.push(tabViewitem2); tabView.items = items; @@ -145,7 +145,7 @@ export function testWhenNavigatingBackToANonCachedPageContainingATabViewWithALis let items = Array(); let tabViewitem = new TabContentItem(); // tabViewitem.title = "List"; - tabViewitem.view = _createListView(); + tabViewitem.content = _createListView(); items.push(tabViewitem); let label = new Label(); @@ -155,7 +155,7 @@ export function testWhenNavigatingBackToANonCachedPageContainingATabViewWithALis aboutLayout.addChild(label); tabViewitem = new TabContentItem(); // tabViewitem.title = "About"; - tabViewitem.view = aboutLayout; + tabViewitem.content = aboutLayout; items.push(tabViewitem); tabView.items = items; @@ -184,7 +184,7 @@ export function testWhenNavigatingBackToANonCachedPageContainingATabViewWithALis TKUnit.waitUntilReady(() => topFrame.currentPage === rootPage); - TKUnit.assert(tabView.items[0].view instanceof ListView, "ListView should be created when navigating back to the main page."); + TKUnit.assert(tabView.items[0].content instanceof ListView, "ListView should be created when navigating back to the main page."); } function tabViewIsFullyLoaded(tabView: BottomNavigation): boolean { @@ -232,8 +232,8 @@ export function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack() { } tabView.items.forEach((item, i) => { - item.view.on("loaded", createLoadedFor(i)); - item.view.on("unloaded", createUnloadedFor(i)); + item.content.on("loaded", createLoadedFor(i)); + item.content.on("unloaded", createUnloadedFor(i)); }); const tabViewPage = new Page(); @@ -252,8 +252,8 @@ export function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack() { TKUnit.assertEqual(topFrame.currentPage, tabViewPage); for (let i = 0; i < itemCount; i++) { - tabView.items[i].view.off("loaded"); - tabView.items[i].view.off("unloaded"); + tabView.items[i].content.off("loaded"); + tabView.items[i].content.off("unloaded"); } helper.goBack(); @@ -267,7 +267,7 @@ export function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack() { function _clickTheFirstButtonInTheListViewNatively(tabView: BottomNavigation) { if (tabView.android) { - const androidListView = tabView.items[0].view.nativeView; + const androidListView = tabView.items[0].content.nativeView; // var viewPager: android.support.v4.view.ViewPager = (tabView)._viewPager; // var androidListView = viewPager.getChildAt(0); var stackLayout = androidListView.getChildAt(0); diff --git a/tests/app/ui/bottom-navigation/bottom-navigation-root-tests.ts b/tests/app/ui/bottom-navigation/bottom-navigation-root-tests.ts index 39bccdb96..c92841c23 100644 --- a/tests/app/ui/bottom-navigation/bottom-navigation-root-tests.ts +++ b/tests/app/ui/bottom-navigation/bottom-navigation-root-tests.ts @@ -47,7 +47,7 @@ function createFrame(i: number, page: Page) { function createTabItem(i: number, frame: Frame) { const tabEntry = new TabContentItem(); // tabEntry.title = "Tab " + i; - tabEntry.view = frame; + tabEntry.content = frame; tabEntry["index"] = i; return tabEntry; diff --git a/tests/app/ui/bottom-navigation/bottom-navigation-tests.ts b/tests/app/ui/bottom-navigation/bottom-navigation-tests.ts index 5678dbdcf..c0afbaf0d 100644 --- a/tests/app/ui/bottom-navigation/bottom-navigation-tests.ts +++ b/tests/app/ui/bottom-navigation/bottom-navigation-tests.ts @@ -27,7 +27,7 @@ export class BottomNavigationTest extends UITest { const label = new Label(); label.text = "Tab " + i; const tabEntry = new TabContentItem(); - tabEntry.view = label; + tabEntry.content = label; items.push(tabEntry); } @@ -208,7 +208,7 @@ export class BottomNavigationTest extends UITest { TKUnit.assertThrows(() => { let item = new TabContentItem(); // item.title = "Tab 0"; - item.view = undefined; + item.content = undefined; tabView.items = [item]; }, "Binding TabNavigation to a TabItem with undefined view should throw."); @@ -221,7 +221,7 @@ export class BottomNavigationTest extends UITest { TKUnit.assertThrows(() => { let item = new TabContentItem(); // item.title = "Tab 0"; - item.view = null; + item.content = null; tabView.items = [item]; }, "Binding TabNavigation to a TabItem with null view should throw."); diff --git a/tests/app/ui/tabs/tabs-navigation-tests.ts b/tests/app/ui/tabs/tabs-navigation-tests.ts index 8489663d1..03e8ca191 100644 --- a/tests/app/ui/tabs/tabs-navigation-tests.ts +++ b/tests/app/ui/tabs/tabs-navigation-tests.ts @@ -23,7 +23,7 @@ function _createContentItems(count: number): Array { const label = new Label(); label.text = "Tab " + i; const tabEntry = new TabContentItem(); - tabEntry.view = label; + tabEntry.content = label; items.push(tabEntry); } @@ -101,12 +101,12 @@ export function testBackNavigationToTabViewWithNestedFramesShouldWork() { let items = Array(); let tabViewitem = new TabContentItem(); // tabViewitem.title = "Item1"; - tabViewitem.view = _createFrameView(); + tabViewitem.content = _createFrameView(); items.push(tabViewitem); let tabViewitem2 = new TabContentItem(); // tabViewitem2.title = "Item2"; - tabViewitem2.view = _createFrameView(); + tabViewitem2.content = _createFrameView(); items.push(tabViewitem2); tabView.items = items; @@ -145,7 +145,7 @@ export function testWhenNavigatingBackToANonCachedPageContainingATabViewWithALis let items = Array(); let tabViewitem = new TabContentItem(); // tabViewitem.title = "List"; - tabViewitem.view = _createListView(); + tabViewitem.content = _createListView(); items.push(tabViewitem); let label = new Label(); @@ -155,7 +155,7 @@ export function testWhenNavigatingBackToANonCachedPageContainingATabViewWithALis aboutLayout.addChild(label); tabViewitem = new TabContentItem(); // tabViewitem.title = "About"; - tabViewitem.view = aboutLayout; + tabViewitem.content = aboutLayout; items.push(tabViewitem); tabView.items = items; @@ -184,7 +184,7 @@ export function testWhenNavigatingBackToANonCachedPageContainingATabViewWithALis TKUnit.waitUntilReady(() => topFrame.currentPage === rootPage); - TKUnit.assert(tabView.items[0].view instanceof ListView, "ListView should be created when navigating back to the main page."); + TKUnit.assert(tabView.items[0].content instanceof ListView, "ListView should be created when navigating back to the main page."); } function tabViewIsFullyLoaded(tabView: Tabs): boolean { @@ -232,8 +232,8 @@ export function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack() { } tabView.items.forEach((item, i) => { - item.view.on("loaded", createLoadedFor(i)); - item.view.on("unloaded", createUnloadedFor(i)); + item.content.on("loaded", createLoadedFor(i)); + item.content.on("unloaded", createUnloadedFor(i)); }); const tabViewPage = new Page(); @@ -252,8 +252,8 @@ export function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack() { TKUnit.assertEqual(topFrame.currentPage, tabViewPage); for (let i = 0; i < itemCount; i++) { - tabView.items[i].view.off("loaded"); - tabView.items[i].view.off("unloaded"); + tabView.items[i].content.off("loaded"); + tabView.items[i].content.off("unloaded"); } helper.goBack(); @@ -267,7 +267,7 @@ export function testLoadedAndUnloadedAreFired_WhenNavigatingAwayAndBack() { function _clickTheFirstButtonInTheListViewNatively(tabView: Tabs) { if (tabView.android) { - const androidListView = tabView.items[0].view.nativeView; + const androidListView = tabView.items[0].content.nativeView; // var viewPager: android.support.v4.view.ViewPager = (tabView)._viewPager; // var androidListView = viewPager.getChildAt(0); var stackLayout = androidListView.getChildAt(0); diff --git a/tests/app/ui/tabs/tabs-root-tests.ts b/tests/app/ui/tabs/tabs-root-tests.ts index 594f4622b..c06f6d0db 100644 --- a/tests/app/ui/tabs/tabs-root-tests.ts +++ b/tests/app/ui/tabs/tabs-root-tests.ts @@ -35,7 +35,7 @@ function createFrame(i: number, page: Page) { function createTabItem(i: number, frame: Frame) { const tabEntry = new TabContentItem(); // tabEntry.title = "Tab " + i; - tabEntry.view = frame; + tabEntry.content = frame; tabEntry["index"] = i; return tabEntry; diff --git a/tests/app/ui/tabs/tabs-tests.ts b/tests/app/ui/tabs/tabs-tests.ts index edb848bdc..2e5d34de6 100644 --- a/tests/app/ui/tabs/tabs-tests.ts +++ b/tests/app/ui/tabs/tabs-tests.ts @@ -27,7 +27,7 @@ export class TabsTest extends UITest { const label = new Label(); label.text = "Tab " + i; const tabEntry = new TabContentItem(); - tabEntry.view = label; + tabEntry.content = label; items.push(tabEntry); } @@ -210,7 +210,7 @@ export class TabsTest extends UITest { TKUnit.assertThrows(() => { let item = new TabContentItem(); // item.title = "Tab 0"; - item.view = undefined; + item.content = undefined; tabView.items = [item]; }, "Binding TabNavigation to a TabItem with undefined view should throw."); @@ -223,7 +223,7 @@ export class TabsTest extends UITest { TKUnit.assertThrows(() => { let item = new TabContentItem(); // item.title = "Tab 0"; - item.view = null; + item.content = null; tabView.items = [item]; }, "Binding TabNavigation to a TabItem with null view should throw."); diff --git a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/BottomNavigationBar.java b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/BottomNavigationBar.java index 29a5c0492..4e2cd7eeb 100644 --- a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/BottomNavigationBar.java +++ b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/BottomNavigationBar.java @@ -201,6 +201,19 @@ public class BottomNavigationBar extends LinearLayout { if (tabItem.title != null && !tabItem.title.isEmpty()) { textView.setText(tabItem.title); textView.setVisibility(VISIBLE); + + if (tabItem.typeFace != null) { + textView.setTypeface(tabItem.typeFace); + } + + if (tabItem.fontSize != 0) { + textView.setTextSize(tabItem.fontSize); + } + + if (tabItem.color != 0) { + textView.setTextColor(tabItem.color); + mTabStrip.setShouldUpdateTabsTextColor(false); + } } else { textView.setVisibility(GONE); } diff --git a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabItemSpec.java b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabItemSpec.java index 2aa6ff08b..1494e407f 100644 --- a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabItemSpec.java +++ b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabItemSpec.java @@ -1,10 +1,14 @@ package org.nativescript.widgets; import android.graphics.drawable.Drawable; +import android.graphics.Typeface; public class TabItemSpec { public String title; + public int fontSize; + public Typeface typeFace; public int iconId; public Drawable iconDrawable; public int backgroundColor; + public int color; } \ No newline at end of file diff --git a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabStrip.java b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabStrip.java index 557be52a1..37cb21c13 100644 --- a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabStrip.java +++ b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabStrip.java @@ -52,6 +52,8 @@ class TabStrip extends LinearLayout { private int mSelectedTabTextColor; private float mTabTextFontSize; + private boolean mShouldUpdateTabsTextColor; + TabStrip(Context context) { this(context, null); } @@ -87,6 +89,8 @@ class TabStrip extends LinearLayout { // Default selected color is the same as mTabTextColor mSelectedTabTextColor = mTabTextColor; + mShouldUpdateTabsTextColor = true; + setMeasureWithLargestChildEnabled(true); } @@ -120,16 +124,22 @@ class TabStrip extends LinearLayout { return mSelectedTabTextColor; } + void setShouldUpdateTabsTextColor(boolean value) { + mShouldUpdateTabsTextColor = value; + } + private void updateTabsTextColor(){ - final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++){ - LinearLayout linearLayout = (LinearLayout)getChildAt(i); - TextView textView = (TextView)linearLayout.getChildAt(1); - if (i == mSelectedPosition){ - textView.setTextColor(mSelectedTabTextColor); - } - else { - textView.setTextColor(mTabTextColor); + if (mShouldUpdateTabsTextColor) { + final int childCount = getChildCount(); + for (int i = 0; i < childCount; i++){ + LinearLayout linearLayout = (LinearLayout)getChildAt(i); + TextView textView = (TextView)linearLayout.getChildAt(1); + if (i == mSelectedPosition){ + textView.setTextColor(mSelectedTabTextColor); + } + else { + textView.setTextColor(mTabTextColor); + } } } } diff --git a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabsBar.java b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabsBar.java index c53661cc7..20dfdfd0c 100644 --- a/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabsBar.java +++ b/tns-core-modules-widgets/android/widgets/src/main/java/org/nativescript/widgets/TabsBar.java @@ -252,7 +252,6 @@ public class TabsBar extends HorizontalScrollView { textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, TAB_VIEW_TEXT_SIZE_SP); textView.setTypeface(Typeface.DEFAULT_BOLD); textView.setEllipsize(TextUtils.TruncateAt.END); - textView.setAllCaps(true); textView.setMaxLines(2); textView.setLayoutParams(new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); textView.setPadding(padding, 0, padding, 0); @@ -280,6 +279,19 @@ public class TabsBar extends HorizontalScrollView { if (tabItem.title != null && !tabItem.title.isEmpty()) { textView.setText(tabItem.title); textView.setVisibility(VISIBLE); + + if (tabItem.typeFace != null) { + textView.setTypeface(tabItem.typeFace); + } + + if (tabItem.fontSize != 0) { + textView.setTextSize(tabItem.fontSize); + } + + if (tabItem.color != 0) { + textView.setTextColor(tabItem.color); + mTabStrip.setShouldUpdateTabsTextColor(false); + } } else { textView.setVisibility(GONE); } 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 8cca2d108..e229ce202 100644 --- a/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts +++ b/tns-core-modules/ui/bottom-navigation/bottom-navigation.android.ts @@ -85,7 +85,7 @@ function initializeNativeClasses() { public onCreateView(inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View { const tabItem = this.tab.items[this.index]; - return tabItem.view.nativeViewProtected; + return tabItem.nativeViewProtected; } } @@ -167,43 +167,58 @@ function initializeNativeClasses() { } function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec { - let iconSource; const tabItemSpec = new org.nativescript.widgets.TabItemSpec(); - // Image and Label children of TabStripItem - // take priority over its `iconSource` and `title` properties - iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource; - tabItemSpec.title = tabStripItem.label ? tabStripItem.label.text : tabStripItem.title; + if (tabStripItem.isLoaded) { + const titleLabel = tabStripItem.label; + let title = titleLabel.text; - if (tabStripItem.backgroundColor instanceof Color) { - tabItemSpec.backgroundColor = tabStripItem.backgroundColor.android; - } + // TEXT-TRANSFORM + const textTransform = titleLabel.style.textTransform; + if (textTransform) { + title = getTransformedText(title, textTransform); + } + tabItemSpec.title = title; - if (iconSource) { - if (iconSource.indexOf(RESOURCE_PREFIX) === 0) { - tabItemSpec.iconId = ad.resources.getDrawableId(iconSource.substr(RESOURCE_PREFIX.length)); - if (tabItemSpec.iconId === 0) { - // TODO: - // traceMissingIcon(iconSource); - } - } else { - let is = new ImageSource(); - if (isFontIconURI(tabStripItem.iconSource)) { - const fontIconCode = tabStripItem.iconSource.split("//")[1]; - const font = tabStripItem.style.fontInternal; - const color = tabStripItem.style.color; - is = fromFontIconCode(fontIconCode, font, color); + // BACKGROUND-COLOR + const backgroundColor = tabStripItem.style.backgroundColor; + if (backgroundColor) { + tabItemSpec.backgroundColor = backgroundColor.android; + } + + // COLOR + const color = titleLabel.style.color; + if (color) { + tabItemSpec.color = color.android; + } + + // FONT + const fontInternal = titleLabel.style.fontInternal; + if (fontInternal) { + tabItemSpec.fontSize = fontInternal.fontSize; + tabItemSpec.typeFace = fontInternal.getAndroidTypeface(); + } + + // ICON + const iconSource = tabStripItem.image && tabStripItem.image.src; + if (iconSource) { + if (iconSource.indexOf(RESOURCE_PREFIX) === 0) { + tabItemSpec.iconId = ad.resources.getDrawableId(iconSource.substr(RESOURCE_PREFIX.length)); + if (tabItemSpec.iconId === 0) { + // TODO: + // traceMissingIcon(iconSource); + } } else { - is = fromFileOrResource(tabStripItem.iconSource); - } + const icon = _getIcon(tabStripItem); - if (is) { - // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. - // tslint:disable-next-line:deprecation - tabItemSpec.iconDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android); - } else { - // TODO: - // traceMissingIcon(iconSource); + if (icon) { + // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. + // tslint:disable-next-line:deprecation + tabItemSpec.iconDrawable = icon; + } else { + // TODO: + // traceMissingIcon(iconSource); + } } } } @@ -211,11 +226,29 @@ function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets return tabItemSpec; } -function setElevation(grid: org.nativescript.widgets.GridLayout, bottomNavigationBar: org.nativescript.widgets.BottomNavigationBar) { +function _getIcon(tabStripItem: TabStripItem): android.graphics.drawable.BitmapDrawable { + const iconSource = tabStripItem.image && tabStripItem.image.src; + + let is: ImageSource; + if (isFontIconURI(iconSource)) { + const fontIconCode = iconSource.split("//")[1]; + const target = tabStripItem.image ? tabStripItem.image : tabStripItem; + const font = target.style.fontInternal; + const color = target.style.color; + is = fromFontIconCode(fontIconCode, font, color); + } else { + is = fromFileOrResource(iconSource); + } + + const image = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android); + + return image; +} + +function setElevation(bottomNavigationBar: org.nativescript.widgets.BottomNavigationBar) { const compat = androidx.core.view.ViewCompat; if (compat.setElevation) { const val = DEFAULT_ELEVATION * layout.getDisplayDensity(); - compat.setElevation(grid, val); compat.setElevation(bottomNavigationBar, val); } } @@ -288,7 +321,7 @@ export class BottomNavigation extends TabNavigationBase { nativeView.addView(bottomNavigationBar); (nativeView).bottomNavigationBar = bottomNavigationBar; - setElevation(nativeView, bottomNavigationBar); + setElevation(bottomNavigationBar); const primaryColor = ad.resources.getPaletteColor(PRIMARY_COLOR, context); if (primaryColor) { @@ -341,12 +374,12 @@ export class BottomNavigation extends TabNavigationBase { toUnload.forEach(index => { const item = items[index]; if (items[index]) { - item.unloadView(item.view); + item.unloadView(item.content); } }); const newItem = items[newIndex]; - const selectedView = newItem && newItem.view; + const selectedView = newItem && newItem.content; if (selectedView instanceof Frame) { selectedView._pushInFrameStackRecursive(); } @@ -354,7 +387,7 @@ export class BottomNavigation extends TabNavigationBase { toLoad.forEach(index => { const item = items[index]; if (this.isLoaded && items[index]) { - item.loadView(item.view); + item.loadView(item.content); } }); } @@ -562,18 +595,11 @@ export class BottomNavigation extends TabNavigationBase { } } - public getTabBarColor(): number { - return this._bottomNavigationBar.getTabTextColor(); - } - - public setTabBarColor(value: number | Color): void { - if (value instanceof Color) { - this._bottomNavigationBar.setTabTextColor(value.android); - this._bottomNavigationBar.setSelectedTabTextColor(value.android); - } else { - this._bottomNavigationBar.setTabTextColor(value); - this._bottomNavigationBar.setSelectedTabTextColor(value); - } + public setTabBarItemTitle(tabStripItem: TabStripItem, value: string): void { + // TODO: Should figure out a way to do it directly with the the nativeView + const tabStripItemIndex = this.tabStrip.items.indexOf(tabStripItem); + const tabItemSpec = createTabItemSpec(tabStripItem); + this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); } public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: android.graphics.drawable.Drawable | Color): void { @@ -583,10 +609,6 @@ export class BottomNavigation extends TabNavigationBase { this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); } - public getTabBarItemColor(tabStripItem: TabStripItem): number { - return tabStripItem.nativeViewProtected.getCurrentTextColor(); - } - public setTabBarItemColor(tabStripItem: TabStripItem, value: number | Color): void { if (typeof value === "number") { tabStripItem.nativeViewProtected.setTextColor(value); @@ -595,45 +617,24 @@ export class BottomNavigation extends TabNavigationBase { } } - public getTabBarItemFontSize(tabStripItem: TabStripItem): { nativeSize: number } { - return { nativeSize: tabStripItem.nativeViewProtected.getTextSize() }; + public setTabBarIconColor(tabStripItem: TabStripItem, value: number | Color): void { + const index = (tabStripItem).index; + const tabBarItem = this._bottomNavigationBar.getViewForItemAt(index); + const imgView = tabBarItem.getChildAt(0); + const drawable = _getIcon(tabStripItem); + + imgView.setImageDrawable(drawable); } - public setTabBarItemFontSize(tabStripItem: TabStripItem, value: number | { nativeSize: number }): void { - if (typeof value === "number") { - tabStripItem.nativeViewProtected.setTextSize(value); - } else { - tabStripItem.nativeViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); - } + public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font): void { + tabStripItem.nativeViewProtected.setTextSize(value.fontSize); + tabStripItem.nativeViewProtected.setTypeface(value.getAndroidTypeface()); } - public getTabBarItemFontInternal(tabStripItem: TabStripItem): android.graphics.Typeface { - return tabStripItem.nativeViewProtected.getTypeface(); - } - - public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font | android.graphics.Typeface): void { - tabStripItem.nativeViewProtected.setTypeface(value instanceof Font ? value.getAndroidTypeface() : value); - } - - private _defaultTransformationMethod: android.text.method.TransformationMethod; - - public getTabBarItemTextTransform(tabStripItem: TabStripItem): "default" { - return "default"; - } - - public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform | "default"): void { - const tv = tabStripItem.nativeViewProtected; - - this._defaultTransformationMethod = this._defaultTransformationMethod || tv.getTransformationMethod(); - - if (value === "default") { - tv.setTransformationMethod(this._defaultTransformationMethod); - tv.setText(tabStripItem.title); - } else { - const result = getTransformedText(tabStripItem.title, value); - tv.setText(result); - tv.setTransformationMethod(null); - } + public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void { + const titleLabel = tabStripItem.label; + const title = getTransformedText(titleLabel.text, value); + tabStripItem.nativeViewProtected.setText(title); } [selectedIndexProperty.setNative](value: number) { 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 e3daa9470..62d0c26d7 100644 --- a/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts +++ b/tns-core-modules/ui/bottom-navigation/bottom-navigation.ios.ts @@ -259,8 +259,10 @@ export class BottomNavigation extends TabNavigationBase { public onLoaded() { super.onLoaded(); + this.setViewControllers(this.items); + const selectedIndex = this.selectedIndex; - const selectedView = this.items && this.items[selectedIndex] && this.items[selectedIndex].view; + const selectedView = this.items && this.items[selectedIndex] && this.items[selectedIndex].content; if (selectedView instanceof Frame) { selectedView._pushInFrameStackRecursive(); } @@ -295,18 +297,18 @@ export class BottomNavigation extends TabNavigationBase { const oldItem = items[oldIndex]; if (oldItem) { oldItem.canBeLoaded = false; - oldItem.unloadView(oldItem.view); + oldItem.unloadView(oldItem.content); } const newItem = items[newIndex]; if (newItem && this.isLoaded) { - const selectedView = items[newIndex].view; + const selectedView = items[newIndex].content; if (selectedView instanceof Frame) { selectedView._pushInFrameStackRecursive(); } newItem.canBeLoaded = true; - newItem.loadView(newItem.view); + newItem.loadView(newItem.content); } super.onSelectedIndexChanged(oldIndex, newIndex); @@ -320,21 +322,8 @@ export class BottomNavigation extends TabNavigationBase { this._ios.tabBar.barTintColor = value instanceof Color ? value.ios : value; } - public getTabBarColor(): UIColor { - return this._ios.tabBar.tintColor; - } - - public setTabBarColor(value: UIColor | Color): void { - this._ios.tabBar.tintColor = value instanceof Color ? value.ios : value; - - if (!this.tabStrip) { - return; - } - - const states = getTitleAttributesForStates(this.tabStrip); - this.tabStrip.items.forEach((tabStripItem) => { - applyStatesToItem(tabStripItem.nativeView, states); - }); + public setTabBarItemTitle(tabStripItem: TabStripItem, value: string): void { + tabStripItem.nativeView.title = value; } public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: UIColor | Color): void { @@ -355,39 +344,25 @@ export class BottomNavigation extends TabNavigationBase { bgView.backgroundColor = value instanceof Color ? value.ios : value; } - public getTabBarItemColor(tabStripItem: TabStripItem): UIColor { - return this._ios.tabBar.tintColor; - } - public setTabBarItemColor(tabStripItem: TabStripItem, value: UIColor | Color): void { - const states = getTitleAttributesForStates(tabStripItem); + const states = getTitleAttributesForStates(tabStripItem.label); applyStatesToItem(tabStripItem.nativeView, states); } - public getTabBarItemFontSize(tabStripItem: TabStripItem): number { - return null; - } + public setTabBarIconColor(tabStripItem: TabStripItem, value: UIColor | Color): void { + const image = this._getIcon(tabStripItem); - public setTabBarItemFontSize(tabStripItem: TabStripItem, value: number | { nativeSize: number }): void { - const states = getTitleAttributesForStates(tabStripItem); - applyStatesToItem(tabStripItem.nativeView, states); - } - - public getTabBarItemFontInternal(tabStripItem: TabStripItem): Font { - return null; + tabStripItem.nativeView.image = image; + tabStripItem.nativeView.selectedImage = image; } public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font): void { - const states = getTitleAttributesForStates(tabStripItem); + const states = getTitleAttributesForStates(tabStripItem.label); applyStatesToItem(tabStripItem.nativeView, states); } - public getTabBarItemTextTransform(tabStripItem: TabStripItem): TextTransform { - return null; - } - public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void { - const title = getTransformedText(tabStripItem.title, value); + const title = getTransformedText(tabStripItem.label.text, value); tabStripItem.nativeView.title = title; } @@ -463,7 +438,7 @@ export class BottomNavigation extends TabNavigationBase { } private getViewController(item: TabContentItem): UIViewController { - let newController: UIViewController = item.view ? item.view.viewController : null; + let newController: UIViewController = item.content ? item.content.viewController : null; if (newController) { (item).setViewController(newController, newController.view); @@ -471,17 +446,17 @@ export class BottomNavigation extends TabNavigationBase { return newController; } - if (item.view.ios instanceof UIViewController) { - newController = item.view.ios; + if (item.content.ios instanceof UIViewController) { + newController = item.content.ios; (item).setViewController(newController, newController.view); - } else if (item.view.ios && item.view.ios.controller instanceof UIViewController) { - newController = item.view.ios.controller; + } else if (item.content.ios && item.content.ios.controller instanceof UIViewController) { + newController = item.content.ios.controller; (item).setViewController(newController, newController.view); } else { - newController = iosView.UILayoutViewController.initWithOwner(new WeakRef(item.view)) as UIViewController; - newController.view.addSubview(item.view.nativeViewProtected); - item.view.viewController = newController; - (item).setViewController(newController, item.view.nativeViewProtected); + newController = iosView.UILayoutViewController.initWithOwner(new WeakRef(item.content)) as UIViewController; + newController.view.addSubview(item.content.nativeViewProtected); + item.content.viewController = newController; + (item).setViewController(newController, item.content.nativeViewProtected); } return newController; @@ -499,7 +474,6 @@ export class BottomNavigation extends TabNavigationBase { items = items.slice(0, maxTabsCount); const controllers = NSMutableArray.alloc().initWithCapacity(length); - const states = getTitleAttributesForStates(this); if (this.tabStrip) { this.tabStrip.setNativeView(this._ios.tabBar); @@ -513,6 +487,7 @@ export class BottomNavigation extends TabNavigationBase { const tabBarItem = this.createTabBarItem(tabStripItem, i); updateTitleAndIconPositions(tabStripItem, tabBarItem, controller); + const states = getTitleAttributesForStates(tabStripItem.label); applyStatesToItem(tabBarItem, states); controller.tabBarItem = tabBarItem; @@ -534,8 +509,15 @@ export class BottomNavigation extends TabNavigationBase { let image: UIImage; let title: string; - image = this._getIcon(item); - title = item.label ? item.label.text : item.title; + if (item.isLoaded) { + image = this._getIcon(item); + title = item.label.text; + + const textTransform = item.label.style.textTransform; + if (textTransform) { + title = getTransformedText(title, textTransform); + } + } const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, image, index); @@ -549,18 +531,21 @@ export class BottomNavigation extends TabNavigationBase { public _getIcon(tabStripItem: TabStripItem): UIImage { // Image and Label children of TabStripItem // take priority over its `iconSource` and `title` properties - const iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource; + const iconSource = tabStripItem.image && tabStripItem.image.src; if (!iconSource) { return null; } - let image: UIImage = this._iconsCache[iconSource]; + const target = tabStripItem.image; + const font = target.style.fontInternal; + const color = target.style.color; + const iconTag = [iconSource, font.fontStyle, font.fontWeight, font.fontSize, font.fontFamily, color].join(";"); + + let image: UIImage = this._iconsCache[iconTag]; if (!image) { let is = new ImageSource; if (isFontIconURI(iconSource)) { const fontIconCode = iconSource.split("//")[1]; - const font = tabStripItem.style.fontInternal; - const color = tabStripItem.style.color; is = fromFontIconCode(fontIconCode, font, color); } else { is = fromFileOrResource(iconSource); @@ -568,7 +553,7 @@ export class BottomNavigation extends TabNavigationBase { if (is && is.ios) { const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode()); - this._iconsCache[iconSource] = originalRenderedImage; + this._iconsCache[iconTag] = originalRenderedImage; image = originalRenderedImage; } else { // TODO @@ -615,6 +600,12 @@ export class BottomNavigation extends TabNavigationBase { return null; } [itemsProperty.setNative](value: TabContentItem[]) { + if (value) { + value.forEach((item: TabContentItem, i) => { + (item).index = i; + }); + } + this.setViewControllers(value); selectedIndexProperty.coerce(this); } diff --git a/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item-common.ts b/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item-common.ts index 71741dd3c..024febd0a 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item-common.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item-common.ts @@ -5,38 +5,15 @@ import { TabNavigationBase } from "../tab-navigation-base"; // Requires import { View, ViewBase, CSSType } from "../../core/view"; - +import { ContentView } from "../../content-view"; export const traceCategory = "TabView"; @CSSType("TabContentItem") -export abstract class TabContentItemBase extends ViewBase implements TabContentItemDefinition, AddChildFromBuilder { - private _view: View; +export abstract class TabContentItemBase extends ContentView implements TabContentItemDefinition, AddChildFromBuilder { - public _addChildFromBuilder(name: string, value: any): void { - if (value instanceof View) { - this.view = value; - } - } - - // TODO: Should we rename this to content? Or even better - inherit ContentView??? - get view(): View { - return this._view; - } - set view(value: View) { - if (this._view !== value) { - if (this._view) { - throw new Error("Changing the view of an already loaded TabContentItem is not currently supported."); - } - - this._view = value; - this._addView(value); - } - } - - public eachChild(callback: (child: ViewBase) => boolean) { - const view = this._view; - if (view) { - callback(view); + public eachChild(callback: (child: View) => boolean) { + if (this.content) { + callback(this.content); } } diff --git a/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.android.ts b/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.android.ts index 409d1cc39..73aba71b0 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.android.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.android.ts @@ -1,15 +1,16 @@ // Types import { TabContentItem as TabContentItemDefinition } from "."; import { TabNavigationBase } from "../tab-navigation-base"; +import { GridLayout } from "../../layouts/grid-layout"; // Requires import { TabContentItemBase, traceCategory } from "./tab-content-item-common"; -import { traceEnabled, traceWrite, traceMessageType } from "../../core/view"; +import { View, traceWrite, traceMessageType } from "../../core/view"; export * from "./tab-content-item-common"; export class TabContentItem extends TabContentItemBase { - public nativeViewProtected: android.widget.TextView; + public nativeViewProtected: org.nativescript.widgets.GridLayout; public tabItemSpec: org.nativescript.widgets.TabItemSpec; public index: number; @@ -17,6 +18,26 @@ export class TabContentItem extends TabContentItemBase { return true; } + public createNativeView() { + const layout = new org.nativescript.widgets.GridLayout(this._context); + layout.addRow(new org.nativescript.widgets.ItemSpec(1, org.nativescript.widgets.GridUnitType.star)); + + return layout; + } + + public initNativeView(): void { + super.initNativeView(); + } + + public _addViewToNativeVisualTree(child: View, atIndex?: number): boolean { + // Set the row property for the child + if (this.nativeViewProtected && child.nativeViewProtected) { + GridLayout.setRow(child, 0); + } + + return super._addViewToNativeVisualTree(child, atIndex); + } + public disposeNativeView(): void { super.disposeNativeView(); (this).canBeLoaded = false; diff --git a/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.d.ts b/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.d.ts index 34ced73c3..e1c8a0180 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.d.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-content-item/tab-content-item.d.ts @@ -4,16 +4,12 @@ */ /** */ import { View, ViewBase } from "../../core/view"; +import { ContentView } from "../../content-view"; /** * Represents a tab navigation content entry. */ -export class TabContentItem extends ViewBase { - /** - * Gets or sets the view of the TabViewItem. - */ - public view: View; - +export class TabContentItem extends ContentView { /** * @private */ diff --git a/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.d.ts b/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.d.ts index 400b158a5..6a11acd77 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.d.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.d.ts @@ -144,6 +144,12 @@ export class TabNavigationBase extends View { */ setTabBarHighlightColor(value: any) + /** + * @private + * Method is intended to be overridden by inheritors and used as "protected" + */ + setTabBarItemTitle(tabStripItem: TabStripItem, value: any): any + /** * @private * Method is intended to be overridden by inheritors and used as "protected" @@ -168,6 +174,12 @@ export class TabNavigationBase extends View { */ setTabBarItemColor(tabStripItem: TabStripItem, value: any): void + /** + * @private + * Method is intended to be overridden by inheritors and used as "protected" + */ + setTabBarIconColor(tabStripItem: TabStripItem, value: any): void + /** * @private * Method is intended to be overridden by inheritors and used as "protected" diff --git a/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.ts b/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.ts index 599a6771a..b72d5640d 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-navigation-base/tab-navigation-base.ts @@ -45,7 +45,7 @@ export class TabNavigationBase extends View implements TabNavigationBaseDefiniti get _selectedView(): View { let selectedIndex = this.selectedIndex; - return selectedIndex > -1 ? this.items[selectedIndex].view : null; + return selectedIndex > -1 ? this.items[selectedIndex].content : null; } get _childrenCount(): number { @@ -72,7 +72,7 @@ export class TabNavigationBase extends View implements TabNavigationBaseDefiniti const items = this.items; if (items) { items.forEach((item, i) => { - callback(item.view); + callback(item.content); }); } } @@ -84,8 +84,8 @@ export class TabNavigationBase extends View implements TabNavigationBaseDefiniti if (newItems) { newItems.forEach(item => { - if (!item.view) { - throw new Error(`TabContentItem must have a view.`); + if (!item.content) { + throw new Error(`TabContentItem must have a content (view).`); } this._addView(item); @@ -152,6 +152,10 @@ export class TabNavigationBase extends View implements TabNavigationBaseDefiniti // overridden by inheritors } + public setTabBarItemTitle(tabStripItem: TabStripItem, value: any): void { + // overridden by inheritors + } + public getTabBarItemBackgroundColor(tabStripItem: TabStripItem): any { // overridden by inheritors return null; @@ -170,6 +174,10 @@ export class TabNavigationBase extends View implements TabNavigationBaseDefiniti // overridden by inheritors } + public setTabBarIconColor(tabStripItem: TabStripItem, value: any): void { + // overridden by inheritors + } + public getTabBarItemFontSize(tabStripItem: TabStripItem): any { // overridden by inheritors return null; diff --git a/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.ts b/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.ts index 9d81137f9..79753759d 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.ts @@ -1,5 +1,6 @@ // Types import { TabStripItem as TabStripItemDefinition } from "."; +import { PropertyChangeData } from "../../../data/observable"; import { TabNavigationBase } from "../tab-navigation-base"; import { TabStrip } from "../tab-strip"; import { Image } from "../../image/image"; @@ -9,10 +10,8 @@ import { AddChildFromBuilder } from "../../core/view"; // Requires import { - View, CSSType, backgroundColorProperty, backgroundInternalProperty, colorProperty, - fontSizeProperty, fontInternalProperty, PseudoClassHandler + View, ViewBase, CSSType, backgroundColorProperty, backgroundInternalProperty, PseudoClassHandler } from "../../core/view"; -import { textTransformProperty, TextTransform } from "../../text-base"; export * from "../../core/view"; export const traceCategory = "TabView"; @@ -23,14 +22,153 @@ export class TabStripItem extends View implements TabStripItemDefinition, AddChi public static selectEvent = "select"; public static unselectEvent = "unselect"; - public title: string; - public iconSource: string; public image: Image; public label: Label; + private _title: string; + private _iconSource: string; + private _highlightedHandler: () => void; private _normalHandler: () => void; + private _labelColorHandler: (args: PropertyChangeData) => void; + private _labelFontHandler: (args: PropertyChangeData) => void; + private _labelTextTransformHandler: (args: PropertyChangeData) => void; + private _labelTextHandler: (args: PropertyChangeData) => void; + + private _imageColorHandler: (args: PropertyChangeData) => void; + private _imageFontHandler: (args: PropertyChangeData) => void; + private _imageSrcHandler: (args: PropertyChangeData) => void; + + get title(): string { + if (this.isLoaded) { + return this.label.text; + } + + return this._title; + } + + set title(value: string) { + this._title = value; + + if (this.isLoaded) { + this.label.text = value; + } + } + + get iconSource(): string { + if (this.isLoaded) { + return this.image.src; + } + + return this._iconSource; + } + + set iconSource(value: string) { + this._iconSource = value; + + if (this.isLoaded) { + this.image.src = value; + } + } + + public onLoaded() { + if (!this.image) { + const image = new Image(); + image.src = this.iconSource; + this.image = image; + this._addView(this.image); + } + + if (!this.label) { + const label = new Label(); + label.text = this.title; + this.label = label; + this._addView(this.label); + } + + super.onLoaded(); + + this._labelColorHandler = this._labelColorHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && tabStripParent.setTabBarItemColor(this, args.value); + }); + this.label.style.on("colorChange", this._labelColorHandler); + + this._labelFontHandler = this._labelFontHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && tabStripParent.setTabBarItemFontInternal(this, args.value); + }); + this.label.style.on("fontInternalChange", this._labelFontHandler); + + this._labelTextTransformHandler = this._labelTextTransformHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && tabStripParent.setTabBarItemTextTransform(this, args.value); + }); + this.label.style.on("textTransformChange", this._labelTextTransformHandler); + + this._labelTextHandler = this._labelTextHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && tabStripParent.setTabBarItemTitle(this, args.value); + }); + this.label.on("textChange", this._labelTextHandler); + + this._imageColorHandler = this._imageColorHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && (tabStripParent).setTabBarIconColor(this, args.value); + }); + this.image.style.on("colorChange", this._imageColorHandler); + + this._imageFontHandler = this._imageFontHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && (tabStripParent).setTabBarIconColor(this, args.value); + }); + this.image.style.on("fontInternalChange", this._imageFontHandler); + + this._imageSrcHandler = this._imageSrcHandler || ((args: PropertyChangeData) => { + const parent = this.parent; + const tabStripParent = parent && parent.parent; + + return tabStripParent && (tabStripParent).setTabBarIconColor(this, args.value); + }); + this.image.on("srcChange", this._imageSrcHandler); + } + + public onUnloaded() { + super.onUnloaded(); + + this.label.style.off("colorChange", this._labelColorHandler); + this.label.style.off("fontInternalChange", this._labelFontHandler); + this.label.style.off("textTransformChange", this._labelTextTransformHandler); + this.label.style.off("textChange", this._labelTextHandler); + + this.image.style.off("colorChange", this._imageColorHandler); + this.image.style.off("fontInternalChange", this._imageFontHandler); + this.image.style.off("srcChange", this._imageSrcHandler); + } + + public eachChild(callback: (child: ViewBase) => boolean) { + if (this.label) { + callback(this.label); + } + + if (this.image) { + callback(this.image); + } + } + public _addChildFromBuilder(name: string, value: any): void { if (name === "Image") { this.image = value; @@ -99,56 +237,4 @@ export class TabStripItem extends View implements TabStripItemDefinition, AddChi [backgroundInternalProperty.setNative](value: any) { // disable the background CSS properties } - - [colorProperty.getDefault](): Color { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.getTabBarItemColor(this); - } - [colorProperty.setNative](value: Color) { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.setTabBarItemColor(this, value); - } - - [fontSizeProperty.getDefault](): { nativeSize: number } { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.getTabBarItemFontSize(this); - } - [fontSizeProperty.setNative](value: number | { nativeSize: number }) { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.setTabBarItemFontSize(this, value); - } - - [fontInternalProperty.getDefault](): any { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.getTabBarItemFontInternal(this); - } - [fontInternalProperty.setNative](value: any) { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.setTabBarItemFontInternal(this, value); - } - - [textTransformProperty.getDefault](): any { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.getTabBarItemTextTransform(this); - } - [textTransformProperty.setNative](value: any) { - const parent = this.parent; - const tabStripParent = parent && parent.parent; - - return tabStripParent && tabStripParent.setTabBarItemTextTransform(this, value); - } } diff --git a/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.ts b/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.ts index 774af491d..bd2280d12 100644 --- a/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.ts +++ b/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.ts @@ -51,6 +51,18 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu } } + public onItemsChanged(oldItems: TabStripItem[], newItems: TabStripItem[]): void { + if (oldItems) { + oldItems.forEach(item => this._removeView(item)); + } + + if (newItems) { + newItems.forEach(item => { + this._addView(item); + }); + } + } + [backgroundColorProperty.getDefault](): Color { const parent = this.parent; @@ -112,7 +124,14 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu return parent && parent.setTabBarHighlightColor(value); } -} +} + +export const itemsProperty = new Property({ + name: "items", valueChanged: (target, oldValue, newValue) => { + target.onItemsChanged(oldValue, newValue); + } +}); +itemsProperty.register(TabStrip); export const iosIconRenderingModeProperty = new Property({ name: "iosIconRenderingMode", defaultValue: "automatic" }); iosIconRenderingModeProperty.register(TabStrip); diff --git a/tns-core-modules/ui/tabs/tabs.android.ts b/tns-core-modules/ui/tabs/tabs.android.ts index 13b4571a7..9fa203fb4 100644 --- a/tns-core-modules/ui/tabs/tabs.android.ts +++ b/tns-core-modules/ui/tabs/tabs.android.ts @@ -82,7 +82,7 @@ function initializeNativeClasses() { public onCreateView(inflater: android.view.LayoutInflater, container: android.view.ViewGroup, savedInstanceState: android.os.Bundle): android.view.View { const tabItem = this.tab.items[this.index]; - return tabItem.view.nativeViewProtected; + return tabItem.nativeViewProtected; } } @@ -284,42 +284,58 @@ function initializeNativeClasses() { } function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets.TabItemSpec { - let iconSource; const tabItemSpec = new org.nativescript.widgets.TabItemSpec(); - if (tabStripItem.backgroundColor instanceof Color) { - tabItemSpec.backgroundColor = tabStripItem.backgroundColor.android; - } + if (tabStripItem.isLoaded) { + const nestedLabel = tabStripItem.label; + let title = nestedLabel.text; - // Image and Label children of TabStripItem - // take priority over its `iconSource` and `title` properties - iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource; - tabItemSpec.title = tabStripItem.label ? tabStripItem.label.text : tabStripItem.title; + // TEXT-TRANSFORM + const textTransform = nestedLabel.style.textTransform; + if (textTransform) { + title = getTransformedText(title, textTransform); + } + tabItemSpec.title = title; - if (iconSource) { - if (iconSource.indexOf(RESOURCE_PREFIX) === 0) { - tabItemSpec.iconId = ad.resources.getDrawableId(iconSource.substr(RESOURCE_PREFIX.length)); - if (tabItemSpec.iconId === 0) { - // TODO - // traceMissingIcon(iconSource); - } - } else { - let is = new ImageSource(); - if (isFontIconURI(tabStripItem.iconSource)) { - const fontIconCode = tabStripItem.iconSource.split("//")[1]; - const font = tabStripItem.style.fontInternal; - const color = tabStripItem.style.color; - is = fromFontIconCode(fontIconCode, font, color); + // BACKGROUND-COLOR + const backgroundColor = tabStripItem.style.backgroundColor; + if (backgroundColor) { + tabItemSpec.backgroundColor = backgroundColor.android; + } + + // COLOR + const color = nestedLabel.style.color; + if (color) { + tabItemSpec.color = color.android; + } + + // FONT + const fontInternal = nestedLabel.style.fontInternal; + if (fontInternal) { + tabItemSpec.fontSize = fontInternal.fontSize; + tabItemSpec.typeFace = fontInternal.getAndroidTypeface(); + } + + // ICON + const iconSource = tabStripItem.image && tabStripItem.image.src; + if (iconSource) { + if (iconSource.indexOf(RESOURCE_PREFIX) === 0) { + tabItemSpec.iconId = ad.resources.getDrawableId(iconSource.substr(RESOURCE_PREFIX.length)); + if (tabItemSpec.iconId === 0) { + // TODO: + // traceMissingIcon(iconSource); + } } else { - is = fromFileOrResource(tabStripItem.iconSource); - } + const icon = _getIcon(tabStripItem); - if (is) { - // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. - tabItemSpec.iconDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android); - } else { - // TODO - // traceMissingIcon(iconSource); + if (icon) { + // TODO: Make this native call that accepts string so that we don't load Bitmap in JS. + // tslint:disable-next-line:deprecation + tabItemSpec.iconDrawable = icon; + } else { + // TODO: + // traceMissingIcon(iconSource); + } } } } @@ -327,6 +343,25 @@ function createTabItemSpec(tabStripItem: TabStripItem): org.nativescript.widgets return tabItemSpec; } +function _getIcon(tabStripItem: TabStripItem): android.graphics.drawable.BitmapDrawable { + const iconSource = tabStripItem.image && tabStripItem.image.src; + + let is = new ImageSource(); + if (isFontIconURI(iconSource)) { + const fontIconCode = iconSource.split("//")[1]; + const target = tabStripItem.image ? tabStripItem.image : tabStripItem; + const font = target.style.fontInternal; + const color = target.style.color; + is = fromFontIconCode(fontIconCode, font, color); + } else { + is = fromFileOrResource(iconSource); + } + + const image = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android); + + return image; +} + let defaultAccentColor: number = undefined; function getDefaultAccentColor(context: android.content.Context): number { if (defaultAccentColor === undefined) { @@ -337,11 +372,15 @@ function getDefaultAccentColor(context: android.content.Context): number { return defaultAccentColor; } -function setElevation(grid: org.nativescript.widgets.GridLayout, tabsBar: org.nativescript.widgets.TabsBar) { +function setElevation(grid: org.nativescript.widgets.GridLayout, tabsBar: org.nativescript.widgets.TabsBar, tabsPosition: string) { const compat = androidx.core.view.ViewCompat; if (compat.setElevation) { const val = DEFAULT_ELEVATION * layout.getDisplayDensity(); - compat.setElevation(grid, val); + + if (tabsPosition === "top") { + compat.setElevation(grid, val); + } + compat.setElevation(tabsBar, val); } } @@ -422,7 +461,7 @@ export class Tabs extends TabsBase { nativeView.addView(tabsBar); (nativeView).tabsBar = tabsBar; - setElevation(nativeView, tabsBar); + setElevation(nativeView, tabsBar, this.tabsPosition); if (accentColor) { tabsBar.setSelectedIndicatorColors([accentColor]); @@ -471,12 +510,12 @@ export class Tabs extends TabsBase { toUnload.forEach(index => { const item = items[index]; if (items[index]) { - item.unloadView(item.view); + item.unloadView(item.content); } }); const newItem = items[newIndex]; - const selectedView = newItem && newItem.view; + const selectedView = newItem && newItem.content; if (selectedView instanceof Frame) { (selectedView)._pushInFrameStackRecursive(); } @@ -484,7 +523,7 @@ export class Tabs extends TabsBase { toLoad.forEach(index => { const item = items[index]; if (this.isLoaded && items[index]) { - item.loadView(item.view); + item.loadView(item.content); } }); } @@ -661,20 +700,6 @@ export class Tabs extends TabsBase { } } - public getTabBarColor(): number { - return this._tabsBar.getTabTextColor(); - } - - public setTabBarColor(value: number | Color): void { - if (value instanceof Color) { - this._tabsBar.setTabTextColor(value.android); - this._tabsBar.setSelectedTabTextColor(value.android); - } else { - this._tabsBar.setTabTextColor(value); - this._tabsBar.setSelectedTabTextColor(value); - } - } - public getTabBarHighlightColor(): number { return getDefaultAccentColor(this._context); } @@ -684,15 +709,18 @@ export class Tabs extends TabsBase { this._tabsBar.setSelectedIndicatorColors([color]); } - public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: android.graphics.drawable.Drawable | Color): void { + public setTabBarItemTitle(tabStripItem: TabStripItem, value: string): void { // TODO: Should figure out a way to do it directly with the the nativeView const tabStripItemIndex = this.tabStrip.items.indexOf(tabStripItem); const tabItemSpec = createTabItemSpec(tabStripItem); this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); } - public getTabBarItemColor(tabStripItem: TabStripItem): number { - return tabStripItem.nativeViewProtected.getCurrentTextColor(); + public setTabBarItemBackgroundColor(tabStripItem: TabStripItem, value: android.graphics.drawable.Drawable | Color): void { + // TODO: Should figure out a way to do it directly with the the nativeView + const tabStripItemIndex = this.tabStrip.items.indexOf(tabStripItem); + const tabItemSpec = createTabItemSpec(tabStripItem); + this.updateAndroidItemAt(tabStripItemIndex, tabItemSpec); } public setTabBarItemColor(tabStripItem: TabStripItem, value: number | Color): void { @@ -703,45 +731,24 @@ export class Tabs extends TabsBase { } } - public getTabBarItemFontSize(tabStripItem: TabStripItem): { nativeSize: number } { - return { nativeSize: tabStripItem.nativeViewProtected.getTextSize() }; + public setTabBarIconColor(tabStripItem: TabStripItem, value: number | Color): void { + const index = (tabStripItem).index; + const tabBarItem = this._tabsBar.getViewForItemAt(index); + const imgView = tabBarItem.getChildAt(0); + const drawable = _getIcon(tabStripItem); + + imgView.setImageDrawable(drawable); } - public setTabBarItemFontSize(tabStripItem: TabStripItem, value: number | { nativeSize: number }): void { - if (typeof value === "number") { - tabStripItem.nativeViewProtected.setTextSize(value); - } else { - tabStripItem.nativeViewProtected.setTextSize(android.util.TypedValue.COMPLEX_UNIT_PX, value.nativeSize); - } + public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font): void { + tabStripItem.nativeViewProtected.setTextSize(value.fontSize); + tabStripItem.nativeViewProtected.setTypeface(value.getAndroidTypeface()); } - public getTabBarItemFontInternal(tabStripItem: TabStripItem): android.graphics.Typeface { - return tabStripItem.nativeViewProtected.getTypeface(); - } - - public setTabBarItemFontInternal(tabStripItem: TabStripItem, value: Font | android.graphics.Typeface): void { - tabStripItem.nativeViewProtected.setTypeface(value instanceof Font ? value.getAndroidTypeface() : value); - } - - private _defaultTransformationMethod: android.text.method.TransformationMethod; - - public getTabBarItemTextTransform(tabStripItem: TabStripItem): "default" { - return "default"; - } - - public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform | "default"): void { - const tv = tabStripItem.nativeViewProtected; - - this._defaultTransformationMethod = this._defaultTransformationMethod || tv.getTransformationMethod(); - - if (value === "default") { - tv.setTransformationMethod(this._defaultTransformationMethod); - tv.setText(tabStripItem.title); - } else { - const result = getTransformedText(tabStripItem.title, value); - tv.setText(result); - tv.setTransformationMethod(null); - } + public setTabBarItemTextTransform(tabStripItem: TabStripItem, value: TextTransform): void { + const nestedLabel = tabStripItem.label; + const title = getTransformedText(nestedLabel.text, value); + tabStripItem.nativeViewProtected.setText(title); } [selectedIndexProperty.setNative](value: number) { diff --git a/tns-core-modules/ui/tabs/tabs.ios.ts b/tns-core-modules/ui/tabs/tabs.ios.ts index aa52dca18..8579f0755 100644 --- a/tns-core-modules/ui/tabs/tabs.ios.ts +++ b/tns-core-modules/ui/tabs/tabs.ios.ts @@ -532,7 +532,7 @@ export class Tabs extends TabsBase { super.onLoaded(); const selectedIndex = this.selectedIndex; - const selectedView = this.items && this.items[selectedIndex] && this.items[selectedIndex].view; + const selectedView = this.items && this.items[selectedIndex] && this.items[selectedIndex].content; if (selectedView instanceof Frame) { (selectedView)._pushInFrameStackRecursive(); } @@ -540,10 +540,8 @@ export class Tabs extends TabsBase { this._ios.dataSource = this._dataSource; this._ios.delegate = this._delegate; - if (!this.tabBarItems) { - const tabStripItems = this.tabStrip ? this.tabStrip.items : null; - this.setTabStripItems(tabStripItems); - } + const tabStripItems = this.tabStrip ? this.tabStrip.items : null; + this.setTabStripItems(tabStripItems); } public onUnloaded() { @@ -611,12 +609,12 @@ export class Tabs extends TabsBase { toUnload.forEach(index => { const item = items[index]; if (items[index]) { - item.unloadView(item.view); + item.unloadView(item.content); } }); const newItem = items[newIndex]; - const selectedView = newItem && newItem.view; + const selectedView = newItem && newItem.content; if (selectedView instanceof Frame) { selectedView._pushInFrameStackRecursive(); } @@ -624,7 +622,7 @@ export class Tabs extends TabsBase { toLoad.forEach(index => { const item = items[index]; if (this.isLoaded && items[index]) { - item.loadView(item.view); + item.loadView(item.content); } }); } @@ -699,7 +697,7 @@ export class Tabs extends TabsBase { // } public getViewController(item: TabContentItem): UIViewController { - let newController: UIViewController = item.view ? item.view.viewController : null; + let newController: UIViewController = item.content ? item.content.viewController : null; if (newController) { (item).setViewController(newController, newController.view); @@ -707,17 +705,17 @@ export class Tabs extends TabsBase { return newController; } - if (item.view.ios instanceof UIViewController) { - newController = item.view.ios; + if (item.content.ios instanceof UIViewController) { + newController = item.content.ios; (item).setViewController(newController, newController.view); - } else if (item.view.ios && item.view.ios.controller instanceof UIViewController) { - newController = item.view.ios.controller; + } else if (item.content.ios && item.content.ios.controller instanceof UIViewController) { + newController = item.content.ios.controller; (item).setViewController(newController, newController.view); } else { - newController = iosView.UILayoutViewController.initWithOwner(new WeakRef(item.view)) as UIViewController; - newController.view.addSubview(item.view.nativeViewProtected); - item.view.viewController = newController; - (item).setViewController(newController, item.view.nativeViewProtected); + newController = iosView.UILayoutViewController.initWithOwner(new WeakRef(item.content)) as UIViewController; + newController.view.addSubview(item.content.nativeViewProtected); + item.content.viewController = newController; + (item).setViewController(newController, item.content.nativeViewProtected); } return newController; @@ -850,8 +848,8 @@ export class Tabs extends TabsBase { let image: UIImage; let title: string; - image = this._getIcon(item); - title = item.label ? item.label.text : item.title; + image = item.isLoaded && this._getIcon(item); + title = item.label && item.label.text; if (!this.tabStrip._hasImage) { this.tabStrip._hasImage = !!image; @@ -884,20 +882,21 @@ export class Tabs extends TabsBase { } public _getIcon(tabStripItem: TabStripItem): UIImage { - // Image and Label children of TabStripItem - // take priority over its `iconSource` and `title` properties - const iconSource = tabStripItem.image ? tabStripItem.image.src : tabStripItem.iconSource; + const iconSource = tabStripItem.image && tabStripItem.image.src; if (!iconSource) { return null; } - let image: UIImage = this._iconsCache[iconSource]; + const target = tabStripItem.image; + const font = target.style.fontInternal; + const color = target.style.color; + const iconTag = [iconSource, font.fontStyle, font.fontWeight, font.fontSize, font.fontFamily, color].join(";"); + + let image: UIImage = this._iconsCache[iconTag]; if (!image) { let is = new ImageSource; if (isFontIconURI(iconSource)) { const fontIconCode = iconSource.split("//")[1]; - const font = tabStripItem.style.fontInternal; - const color = tabStripItem.style.color; is = fromFontIconCode(fontIconCode, font, color); } else { is = fromFileOrResource(iconSource); @@ -905,7 +904,7 @@ export class Tabs extends TabsBase { if (is && is.ios) { const originalRenderedImage = is.ios.imageWithRenderingMode(this._getIconRenderingMode()); - this._iconsCache[iconSource] = originalRenderedImage; + this._iconsCache[iconTag] = originalRenderedImage; image = originalRenderedImage; } else { // TODO diff --git a/tns-platform-declarations/android/org.nativescript.widgets.d.ts b/tns-platform-declarations/android/org.nativescript.widgets.d.ts index b78e57aa2..dc17e7638 100644 --- a/tns-platform-declarations/android/org.nativescript.widgets.d.ts +++ b/tns-platform-declarations/android/org.nativescript.widgets.d.ts @@ -452,9 +452,12 @@ export class TabItemSpec { title: string; + fontSize: number; + typeFace: android.graphics.Typeface; iconId: number; iconDrawable: android.graphics.drawable.Drawable; backgroundColor: number; + color: number; } export namespace image {