diff --git a/e2e/ui-tests-app/app/tabs/main-page.ts b/e2e/ui-tests-app/app/tabs/main-page.ts
index 625fa25c69..33d8ab2c81 100644
--- a/e2e/ui-tests-app/app/tabs/main-page.ts
+++ b/e2e/ui-tests-app/app/tabs/main-page.ts
@@ -1,8 +1,9 @@
import { EventData } from "tns-core-modules/data/observable";
-import { SubMainPageViewModel } from "../sub-main-page-view-model";
import { WrapLayout } from "tns-core-modules/ui/layouts/wrap-layout";
import { Page } from "tns-core-modules/ui/page";
+import { SubMainPageViewModel } from "../sub-main-page-view-model";
+
export function pageLoaded(args: EventData) {
const page = args.object;
const wrapLayout = page.getViewById("wrapLayoutWithExamples");
@@ -10,7 +11,7 @@ export function pageLoaded(args: EventData) {
}
export function loadExamples() {
- const examples = new Map();
+ const examples = new Map();
examples.set("tabs", "tabs/tabs-page");
examples.set("issue-5470", "tabs/issue-5470");
examples.set("background-color", "tabs/background-color-page");
@@ -18,8 +19,10 @@ export function loadExamples() {
examples.set("icon-title-placement", "tabs/icon-title-placement");
examples.set("icon-change", "tabs/icon-change");
examples.set("swipe-enabled", "tabs/swipe-enabled");
+ examples.set("strip-item", "tabs/tab-strip-item-page");
+ examples.set("strip-items", "tabs/tab-strip-items-page");
examples.set("tabs-position", "tabs/tabs-position-page");
examples.set("tabs-binding", "tabs/tabs-binding-page");
-
+
return examples;
}
diff --git a/e2e/ui-tests-app/app/tabs/main-page.xml b/e2e/ui-tests-app/app/tabs/main-page.xml
index 33306f0d02..79cc239910 100644
--- a/e2e/ui-tests-app/app/tabs/main-page.xml
+++ b/e2e/ui-tests-app/app/tabs/main-page.xml
@@ -3,4 +3,4 @@
-
\ No newline at end of file
+
diff --git a/e2e/ui-tests-app/app/tabs/tab-strip-item-page.xml b/e2e/ui-tests-app/app/tabs/tab-strip-item-page.xml
new file mode 100644
index 0000000000..e5f9c41ba4
--- /dev/null
+++ b/e2e/ui-tests-app/app/tabs/tab-strip-item-page.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/e2e/ui-tests-app/app/tabs/tab-strip-items-page.xml b/e2e/ui-tests-app/app/tabs/tab-strip-items-page.xml
new file mode 100644
index 0000000000..323109806e
--- /dev/null
+++ b/e2e/ui-tests-app/app/tabs/tab-strip-items-page.xml
@@ -0,0 +1,88 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.d.ts b/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.d.ts
index 2506803fc9..7d82cb3820 100644
--- a/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.d.ts
+++ b/tns-core-modules/ui/tab-navigation-base/tab-strip-item/tab-strip-item.d.ts
@@ -4,6 +4,8 @@
*/ /** */
import { View, EventData } from "../../core/view";
+import { Image } from "../../image/image";
+import { Label } from "../../label/label";
/**
* Represents a tab strip entry.
@@ -19,6 +21,16 @@ export class TabStripItem extends View {
*/
iconSource: string;
+ /**
+ * Gets or sets the label of the tab strip entry.
+ */
+ label: Label;
+
+ /**
+ * Gets or sets the image of the tab strip entry.
+ */
+ image: Image;
+
/**
* String value used when hooking to the tap event.
*/
diff --git a/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.d.ts b/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.d.ts
index d6b5dc041b..70b5afe17e 100644
--- a/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.d.ts
+++ b/tns-core-modules/ui/tab-navigation-base/tab-strip/tab-strip.d.ts
@@ -21,6 +21,16 @@ export class TabStrip extends View {
* Gets or sets the icon rendering mode on iOS
*/
iosIconRenderingMode: "automatic" | "alwaysOriginal" | "alwaysTemplate";
+
+ /**
+ * @private
+ */
+ _hasImage: boolean;
+
+ /**
+ * @private
+ */
+ _hasTitle: boolean;
}
export const iosIconRenderingModeProperty: Property;
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 d0417dbd89..2ff16e8302 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
@@ -14,6 +14,8 @@ export const traceCategory = "TabView";
export class TabStrip extends View implements TabStripDefinition, AddChildFromBuilder, AddArrayFromBuilder {
public items: TabStripItem[];
public iosIconRenderingMode: "automatic" | "alwaysOriginal" | "alwaysTemplate";
+ public _hasImage: boolean;
+ public _hasTitle: boolean;
public eachChild(callback: (child: ViewBase) => boolean) {
const items = this.items;
@@ -48,7 +50,7 @@ export class TabStrip extends View implements TabStripDefinition, AddChildFromBu
}
[backgroundColorProperty.setNative](value: Color) {
const parent = this.parent;
-
+
return parent && parent.setTabBarBackgroundColor(value);
}
diff --git a/tns-core-modules/ui/tabs/tabs.android.ts b/tns-core-modules/ui/tabs/tabs.android.ts
index 7d4b1677e4..5aab66fe97 100644
--- a/tns-core-modules/ui/tabs/tabs.android.ts
+++ b/tns-core-modules/ui/tabs/tabs.android.ts
@@ -234,29 +234,34 @@ function initializeNativeClasses() {
}
function createTabItemSpec(item: TabStripItem): org.nativescript.widgets.TabItemSpec {
- const result = new org.nativescript.widgets.TabItemSpec();
- result.title = item.title;
-
- if (item.iconSource) {
- if (item.iconSource.indexOf(RESOURCE_PREFIX) === 0) {
- result.iconId = ad.resources.getDrawableId(item.iconSource.substr(RESOURCE_PREFIX.length));
- if (result.iconId === 0) {
+ let iconSource;
+ const tabItemSpec = new org.nativescript.widgets.TabItemSpec();
+
+ // Image and Label children of TabStripItem
+ // take priority over its `iconSource` and `title` properties
+ iconSource = item.image ? item.image.src : item.iconSource;
+ tabItemSpec.title = item.label ? item.label.text : item.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(item.iconSource);
+ // traceMissingIcon(iconSource);
}
} else {
- const is = fromFileOrResource(item.iconSource);
+ const is = fromFileOrResource(iconSource);
if (is) {
// TODO: Make this native call that accepts string so that we don't load Bitmap in JS.
- result.iconDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android);
+ tabItemSpec.iconDrawable = new android.graphics.drawable.BitmapDrawable(application.android.context.getResources(), is.android);
} else {
// TODO
- // traceMissingIcon(item.iconSource);
+ // traceMissingIcon(iconSource);
}
}
}
- return result;
+ return tabItemSpec;
}
let defaultAccentColor: number = undefined;
diff --git a/tns-core-modules/ui/tabs/tabs.d.ts b/tns-core-modules/ui/tabs/tabs.d.ts
index 67cdd0b264..17e740e913 100644
--- a/tns-core-modules/ui/tabs/tabs.d.ts
+++ b/tns-core-modules/ui/tabs/tabs.d.ts
@@ -1,81 +1,83 @@
/**
- * Contains the TabView class, which represents a standard content component with tabs.
- * @module "ui/tab-view"
+ * Contains the Tabs class, which represents a tab navigation component.
+ * @module "ui/tabs"
*/ /** */
- import { Property, EventData } from "../core/view";
- import { TabNavigationBase, SelectedIndexChangedEventData } from "../tab-navigation-base/tab-navigation-base";
- import { TabContentItem } from "../tab-navigation-base/tab-content-item";
- import { TabStrip } from "../tab-navigation-base/tab-strip";
+import { EventData, Property } from "../core/view";
+import { TabContentItem } from "../tab-navigation-base/tab-content-item";
+import {
+ SelectedIndexChangedEventData, TabNavigationBase
+} from "../tab-navigation-base/tab-navigation-base";
+import { TabStrip } from "../tab-navigation-base/tab-strip";
- export * from "../tab-navigation-base/tab-content-item";
- export * from "../tab-navigation-base/tab-navigation-base";
- export * from "../tab-navigation-base/tab-strip";
- export * from "../tab-navigation-base/tab-strip-item";
-
- /**
- * Represents a swipeable tabs view.
- */
- export class Tabs extends TabNavigationBase {
- /**
- * Gets or sets the items of the Tabs.
- */
- items: Array;
-
- /**
- * Gets or sets the tab strip of the Tabs.
- */
- tabStrip: TabStrip;
-
- /**
- * Gets or sets the selectedIndex of the Tabs.
- */
- selectedIndex: number;
+export * from "../tab-navigation-base/tab-content-item";
+export * from "../tab-navigation-base/tab-navigation-base";
+export * from "../tab-navigation-base/tab-strip";
+export * from "../tab-navigation-base/tab-strip-item";
- /**
- * Gets or sets the swipe enabled state of the Tabs.
- */
- swipeEnabled: boolean;
+/**
+ * Represents a swipeable tabs view.
+ */
+export class Tabs extends TabNavigationBase {
+ /**
+ * Gets or sets the items of the Tabs.
+ */
+ items: Array;
- /**
- * Gets or sets the number of offscreen preloaded tabs of the Tabs.
- */
- offscreenTabLimit: number;
+ /**
+ * Gets or sets the tab strip of the Tabs.
+ */
+ tabStrip: TabStrip;
- /**
- * Gets or sets the position state of the Tabs.
- */
- tabsPosition: "top" | "bottom";
-
- /**
- * Gets the native [android widget](http://developer.android.com/reference/android/support/v4/view/ViewPager.html) that represents the user interface for this component. Valid only when running on Android OS.
- */
- android: any /* android.view.View */; //android.support.v4.view.ViewPager;
-
- /**
- * Gets the native iOS [UITabBarController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITabBarController_Class/) that represents the user interface for this component. Valid only when running on iOS.
- */
- ios: any /* UITabBarController */;
-
- /**
- * String value used when hooking to the selectedIndexChanged event.
- */
- public static selectedIndexChangedEvent: string;
-
- /**
- * A basic method signature to hook an event listener (shortcut alias to the addEventListener method).
- * @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change").
- * @param callback - Callback function which will be executed when event is raised.
- * @param thisArg - An optional parameter which will be used as `this` context for callback execution.
- */
- on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
-
- /**
- * Raised when the selected index changes.
- */
- on(event: "selectedIndexChanged", callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any);
- }
-
- export const itemsProperty: Property;
- export const tabStripProperty: Property
- export const selectedIndexProperty: Property;
+ /**
+ * Gets or sets the selectedIndex of the Tabs.
+ */
+ selectedIndex: number;
+
+ /**
+ * Gets or sets the swipe enabled state of the Tabs.
+ */
+ swipeEnabled: boolean;
+
+ /**
+ * Gets or sets the number of offscreen preloaded tabs of the Tabs.
+ */
+ offscreenTabLimit: number;
+
+ /**
+ * Gets or sets the position state of the Tabs.
+ */
+ tabsPosition: "top" | "bottom";
+
+ /**
+ * Gets the native [android widget](http://developer.android.com/reference/android/support/v4/view/ViewPager.html) that represents the user interface for this component. Valid only when running on Android OS.
+ */
+ android: any /* android.view.View */; //android.support.v4.view.ViewPager;
+
+ /**
+ * Gets the native iOS [UITabBarController](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITabBarController_Class/) that represents the user interface for this component. Valid only when running on iOS.
+ */
+ ios: any /* UITabBarController */;
+
+ /**
+ * String value used when hooking to the selectedIndexChanged event.
+ */
+ public static selectedIndexChangedEvent: string;
+
+ /**
+ * A basic method signature to hook an event listener (shortcut alias to the addEventListener method).
+ * @param eventNames - String corresponding to events (e.g. "propertyChange"). Optionally could be used more events separated by `,` (e.g. "propertyChange", "change").
+ * @param callback - Callback function which will be executed when event is raised.
+ * @param thisArg - An optional parameter which will be used as `this` context for callback execution.
+ */
+ on(eventNames: string, callback: (data: EventData) => void, thisArg?: any);
+
+ /**
+ * Raised when the selected index changes.
+ */
+ on(event: "selectedIndexChanged", callback: (args: SelectedIndexChangedEventData) => void, thisArg?: any);
+}
+
+export const itemsProperty: Property;
+export const tabStripProperty: Property
+export const selectedIndexProperty: Property;
diff --git a/tns-core-modules/ui/tabs/tabs.ios.ts b/tns-core-modules/ui/tabs/tabs.ios.ts
index 38eea43495..c96249f6ed 100644
--- a/tns-core-modules/ui/tabs/tabs.ios.ts
+++ b/tns-core-modules/ui/tabs/tabs.ios.ts
@@ -81,23 +81,11 @@ class UIPageViewControllerImpl extends UIPageViewController {
tabBar.items = NSArray.arrayWithArray(tabBarItems);
}
- // tabBar.items = >NSArray.alloc().initWithArray([
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // ]);
-
tabBar.delegate = this.tabBarDelegate = MDCTabBarDelegateImpl.initWithOwner(new WeakRef(owner));
- tabBar.itemAppearance = MDCTabBarItemAppearance.Titles;
+ // Initially set `itemAppearance` to TitledImages.
+ // Reassign if needed when items available.
+ // Other combinations do not work.
+ tabBar.itemAppearance = MDCTabBarItemAppearance.TitledImages;
tabBar.tintColor = UIColor.blueColor;
tabBar.barTintColor = UIColor.whiteColor;
tabBar.setTitleColorForState(UIColor.blackColor, MDCTabBarItemState.Normal);
@@ -856,33 +844,20 @@ export class Tabs extends TabsBase {
public setTabStripItems(items: Array) {
const tabBarItems = [];
- items.forEach((item: TabStripItem, i, arr) => {
- const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(item.title, null, 0);
+ items.forEach((item: TabStripItem, i) => {
+ const tabBarItem = this.createTabBarItem(item, i);
tabBarItems.push(tabBarItem);
item.setNativeView(tabBarItem);
});
+
this.tabBarItems = tabBarItems;
if (this.viewController && this.viewController.tabBar) {
+ this.viewController.tabBar.itemAppearance = this._getTabBarItemAppearance();
this.viewController.tabBar.items = NSArray.arrayWithArray(tabBarItems);
this.tabStrip.setNativeView(this.viewController.tabBar);
}
- // tabBar.items = >NSArray.alloc().initWithArray([
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // UITabBarItem.alloc().initWithTitleImageTag("Test", null, 0),
- // ]);
-
// const length = items ? items.length : 0;
// if (length === 0) {
// this._tabLayout.setItems(null, null);
@@ -905,6 +880,41 @@ export class Tabs extends TabsBase {
// });
}
+ private createTabBarItem(item: TabStripItem, index: number): UITabBarItem {
+ let image: UIImage;
+ let title: string;
+
+ // Image and Label children of TabStripItem
+ // take priority over its `iconSource` and `title` properties
+ image = item.image ? this._getIcon(item.image.src) : this._getIcon(item.iconSource);
+ title = item.label ? item.label.text : item.title;
+
+ if (!this.tabStrip._hasImage) {
+ this.tabStrip._hasImage = !!image;
+ }
+
+ if (!this.tabStrip._hasTitle) {
+ this.tabStrip._hasTitle = !!title;
+ }
+
+ const tabBarItem = UITabBarItem.alloc().initWithTitleImageTag(title, image, index);
+
+ return tabBarItem;
+ }
+
+ private _getTabBarItemAppearance(): MDCTabBarItemAppearance {
+ let itemAppearance;
+ if (this.tabStrip._hasImage && this.tabStrip._hasTitle) {
+ itemAppearance = MDCTabBarItemAppearance.TitledImages;
+ } else if (this.tabStrip._hasImage) {
+ itemAppearance = MDCTabBarItemAppearance.Images;
+ } else {
+ itemAppearance = MDCTabBarItemAppearance.Titles;
+ }
+
+ return itemAppearance;
+ }
+
private _getIconRenderingMode(): UIImageRenderingMode {
return UIImageRenderingMode.AlwaysOriginal;
}
@@ -1059,4 +1069,4 @@ export class Tabs extends TabsBase {
// function applyStatesToItem(item: UITabBarItem, states: TabStates) {
// item.setTitleTextAttributesForState(states.normalState, UIControlState.Normal);
// item.setTitleTextAttributesForState(states.selectedState, UIControlState.Selected);
-// }
\ No newline at end of file
+// }