BottomTabBar

API Reference: UI.BottomTabBar

BottomTabBar is an UI object. It is used for navigating between pages using tab bar items. Each tab bar item has title, icon and page. If the individual tab has an Icon, icons must be set two types as selected and normal.

TypeScript code blocks includes example of how to implement, override & add components with theme. Create page with UI-Editor to make your page themeable and then able to implement themeable components programmatically. Once page created with UI-Editor, it generates class under scripts/generated/pages. Extend that class with below typescript classes.

On Android side, you can not add more than five tab bar items to bottom tab bar.

scripts/app.ts
scripts/pages/pgProfile.ts
scripts/pages/pgMessages.js
scripts/pages/pgSettings.js
scripts/app.ts
import Image = require("sf-core/ui/image");
import Router = require("@smartface/router/src/native/NativeRouter");
import BottomTabBarRouter = require("@smartface/router/src/native/BottomTabBarRouter");
import Route = require("@smartface/router/src/router/Route");
import Color = require('sf-core/ui/color');
import Page1 from "pages/pgProfile";
import Page2 from "pages/pgMessages";
import Page3 from "pages/pgSettings";
const router = Router.of({
path: "/",
isRoot: true,
routes: [
BottomTabBarRouter.of({
path: "/btb",
to: "/btb/tab1/page1",
tabbarParams: () => ({
ios: { visible: false },
itemColor: {
normal: Color.BLACK,
selected: Color.WHITE
},
backgroundColor: Color.create("#00A1F1")
}),
items: () => [{ title: "Profile", icon: Image.createFromFile("images://profile.png") },
{ title: "Messages", icon: Image.createFromFile("images://messages.png") },
{ title: "Settings", icon: Image.createFromFile("images://settings.png") }],
// tab1
routes: [
// tab1
Route.of({
path: "/btb/tab1/page1",
build: (router, route) => {
return new Page1(router);
}
}),
// tab2
Route.of({
path: "/btb/tab2/page2",
build: (router, route) => {
return new Page2(router);
}
}),
// tab3
Route.of({
path: "/btb/tab3/page3",
build: (router, route) => {
return new Page3(router);
}
})
]
})
]
});
router.push("/btb");
export = router;
scripts/pages/pgProfile.ts
import PgProfileDesign from 'generated/pages/pgProfile';
import FlexLayout = require('sf-core/ui/flexlayout');
import Label = require("sf-core/ui/label");
//You should create new Page from UI-Editor and extend with it.
export default class PgProfile extends PgProfileDesign {
lbl: Label;
constructor(router) {
super();
// Overrides super.onShow method
this.onShow = onShow.bind(this, this.onShow.bind(this));
// Overrides super.onLoad method
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
this.layout.flexDirection = FlexLayout.FlexDirection.ROW;
this.layout.justifyContent = FlexLayout.JustifyContent.CENTER;
this.layout.alignItems = FlexLayout.AlignItems.CENTER;
}
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
* @param {function} superOnShow super onShow function
* @param {Object} parameters passed from Router.go function
*/
function onShow(superOnShow: () => void) {
superOnShow();
}
/**
* @event onLoad
* This event is called once when page is created.
* @param {function} superOnLoad super onLoad function
*/
function onLoad(superOnLoad: () => void) {
superOnLoad();
this.lbl = new Label({
text: "Profile"
});
this.layout.addChild(this.lbl, "lbl", ".sf-label", {
textColor: "#808080",
font: {
size: 20,
bold: true,
italic: false,
family: "Arial",
style: "Semibold"
}
});
}
scripts/pages/pgMessages.js
import PgMessagesDesign from 'generated/pages/pgMessages';
import FlexLayout = require('sf-core/ui/flexlayout');
import Label = require("sf-core/ui/label");
//You should create new Page from UI-Editor and extend with it.
export default class PgMessages extends PgMessagesDesign {
lbl: Label;
constructor(router) {
super();
// Overrides super.onShow method
this.onShow = onShow.bind(this, this.onShow.bind(this));
// Overrides super.onLoad method
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
this.layout.flexDirection = FlexLayout.FlexDirection.ROW;
this.layout.justifyContent = FlexLayout.JustifyContent.CENTER;
this.layout.alignItems = FlexLayout.AlignItems.CENTER;
}
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
* @param {function} superOnShow super onShow function
* @param {Object} parameters passed from Router.go function
*/
function onShow(superOnShow: () => void) {
superOnShow();
}
/**
* @event onLoad
* This event is called once when page is created.
* @param {function} superOnLoad super onLoad function
*/
function onLoad(superOnLoad: () => void) {
superOnLoad();
this.lbl = new Label({
text: "Messages"
});
this.layout.addChild(this.lbl, "lbl", ".sf-label", {
textColor: "#808080",
font: {
size: 20,
bold: true,
italic: false,
family: "Arial",
style: "Semibold"
}
});
}
scripts/pages/pgSettings.js
import PgSettingsDesign from 'generated/pages/pgSettings';
import FlexLayout = require('sf-core/ui/flexlayout');
import Label = require("sf-core/ui/label");
//You should create new Page from UI-Editor and extend with it.
export default class PgSettings extends PgSettingsDesign {
lbl: Label;
constructor(router) {
super();
// Overrides super.onShow method
this.onShow = onShow.bind(this, this.onShow.bind(this));
// Overrides super.onLoad method
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
this.layout.flexDirection = FlexLayout.FlexDirection.ROW;
this.layout.justifyContent = FlexLayout.JustifyContent.CENTER;
this.layout.alignItems = FlexLayout.AlignItems.CENTER;
}
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
* @param {function} superOnShow super onShow function
* @param {Object} parameters passed from Router.go function
*/
function onShow(superOnShow: () => void) {
superOnShow();
}
/**
* @event onLoad
* This event is called once when page is created.
* @param {function} superOnLoad super onLoad function
*/
function onLoad(superOnLoad: () => void) {
superOnLoad();
this.lbl = new Label({
text: "Settings"
});
this.layout.addChild(this.lbl, "lbl", ".sf-label", {
textColor: "#808080",
font: {
size: 20,
bold: true,
italic: false,
family: "Arial",
style: "Semibold"
}
});
}
scripts/app.js
scripts/pages/pgProfile.js
scripts/pages/pgMessages.js
scripts/pages/pgSettings.js
scripts/app.js
const Image = require("sf-core/ui/image");
const Router = require("@smartface/router/src/native/NativeRouter");
const BottomTabBarRouter = require("@smartface/router/src/native/BottomTabBarRouter");
const Route = require("@smartface/router/src/router/Route");
const Color = require('sf-core/ui/color');
const Page1 = require("pages/pgProfile");
const Page2 = require("pages/pgMessages");
const Page3 = require("pages/pgSettings");
const router = Router.of({
path: "/",
isRoot: true,
routes: [
BottomTabBarRouter.of({
path: "/btb",
to: "/btb/tab1/page1",
tabbarParams: () => ({
ios: { visible: false },
itemColor: {
normal: Color.BLACK,
selected: Color.WHITE
},
backgroundColor: Color.create("#00A1F1")
}),
items: () => [{ title: "Profile", icon: Image.createFromFile("images://profile.png") },
{ title: "Messages", icon: Image.createFromFile("images://messages.png") },
{ title: "Settings", icon: Image.createFromFile("images://settings.png") }],
// tab1
routes: [
// tab1
Route.of({
path: "/btb/tab1/page1",
build: (router, route) => {
return new Page1(router);
}
}),
// tab2
Route.of({
path: "/btb/tab2/page2",
build: (router, route) => {
return new Page2(router);
}
}),
// tab3
Route.of({
path: "/btb/tab3/page3",
build: (router, route) => {
return new Page3(router);
}
})
]
})
]
});
router.push("/btb");
scripts/pages/pgProfile.js
const Color = require("sf-core/ui/color");
const Font = require("sf-core/ui/font");
const FlexLayout = require("sf-core/ui/flexlayout");
const Label = require("sf-core/ui/label");
const Page = require("sf-core/ui/page");
const extend = require("js-base/core/extend");
var Page1 = extend(Page)(
function(_super) {
_super(this, {
onLoad: function(params) {
this.headerBar.visible = false;
this.layout.flexDirection = FlexLayout.FlexDirection.ROW;
this.layout.justifyContent = FlexLayout.JustifyContent.CENTER;
this.layout.alignItems = FlexLayout.AlignItems.CENTER;
var lbl = new Label({
text: "Profile",
textColor: Color.GRAY,
font: Font.create("Arial", 20, Font.BOLD),
});
this.layout.addChild(lbl);
}
});
}
);
module.exports = Page1;
scripts/pages/pgMessages.js
const Color = require("sf-core/ui/color");
const Font = require("sf-core/ui/font");
const FlexLayout = require("sf-core/ui/flexlayout");
const Label = require("sf-core/ui/label");
const Page = require("sf-core/ui/page");
const extend = require("js-base/core/extend");
var Page2 = extend(Page)(
function(_super) {
_super(this, {
onLoad: function(params) {
this.headerBar.visible = false;
this.layout.flexDirection = FlexLayout.FlexDirection.ROW;
this.layout.justifyContent = FlexLayout.JustifyContent.CENTER;
this.layout.alignItems = FlexLayout.AlignItems.CENTER;
var lbl = new Label({
text: "Messages",
textColor: Color.GRAY,
font: Font.create("Arial", 20, Font.BOLD),
});
this.layout.addChild(lbl);
}
});
}
);
module.exports = Page2;
scripts/pages/pgSettings.js
const Color = require("sf-core/ui/color");
const FlexLayout = require("sf-core/ui/flexlayout");
const Font = require("sf-core/ui/font");
const Label = require("sf-core/ui/label");
const Page = require("sf-core/ui/page");
const extend = require("js-base/core/extend");
var Page3 = extend(Page)(
function(_super) {
_super(this, {
onLoad: function(params) {
this.headerBar.visible = false;
this.layout.flexDirection = FlexLayout.FlexDirection.ROW;
this.layout.justifyContent = FlexLayout.JustifyContent.CENTER;
this.layout.alignItems = FlexLayout.AlignItems.CENTER;
var lbl = new Label({
text: "Settings",
textColor: Color.GRAY,
font: Font.create("Arial", 20, Font.BOLD),
});
this.layout.addChild(lbl);
}
});
}
);
module.exports = Page3;

Custom Icons for iOS

Please check this guideline before choosing your custom TabBarItem ​icons.

Android Tabbar Optimization

To save time by loading Tabbar, you can optionally call the constructor function in advance.

BottomTabbar Badge

BottomTabBar Badge has a circular or elliptical background, displayed on top-right to the BottomTabBarItem.

scripts/app.ts
scripts/app.js
scripts/app.ts
import Image = require("sf-core/ui/image");
import Router = require("@smartface/router/src/native/NativeRouter");
import BottomTabBarRouter = require("@smartface/router/src/native/BottomTabBarRouter");
import Route = require("@smartface/router/src/router/Route");
import Color = require('sf-core/ui/color');
import Page1 from "pages/pgProfile";
import Page2 from "pages/pgMessages";
import Page3 from "pages/pgSettings";
import TabBarItem = require("sf-core/ui/tabbaritem");
let btbItemMessages = new TabBarItem();
btbItemMessages.title = "Messages";
btbItemMessages.icon = Image.createFromFile("images://smartface.png");
btbItemMessages.badge.text = "1000";
btbItemMessages.badge.visible = true; //default false
if (parseInt(btbItemMessages.badge.text) > 99) {
btbItemMessages.badge.text = "99+";
}
const router = Router.of({
path: "/",
isRoot: true,
routes: [
BottomTabBarRouter.of({
path: "/btb",
to: "/btb/tab1/page1",
tabbarParams: () => ({
ios: { visible: false },
itemColor: {
normal: Color.BLACK,
selected: Color.WHITE
},
backgroundColor: Color.create("#00A1F1")
}),
items: () => [{ title: "Profile", icon: Image.createFromFile("images://profile.png") },
btbItemMessages,
{ title: "Settings", icon: Image.createFromFile("images://settings.png") }],
// tab1
routes: [
// tab1
Route.of({
path: "/btb/tab1/page1",
build: (router, route) => {
return new Page1(router);
}
}),
// tab2
Route.of({
path: "/btb/tab2/page2",
build: (router, route) => {
return new Page2(router);
}
}),
// tab3
Route.of({
path: "/btb/tab3/page3",
build: (router, route) => {
return new Page3(router);
}
})
]
})
]
});
router.push("/btb");
export = router;
scripts/app.js
const Router = require("@smartface/router/src/native/NativeRouter");
const BottomTabBarRouter = require("@smartface/router/src/native/BottomTabBarRouter");
const Route = require("@smartface/router/src/router/Route");
const TabBarItem = require("sf-core/ui/tabbaritem");
const Color = require('sf-core/ui/color');
const Image = require("sf-core/ui/image");
const Page1 = require("pages/page1");
const Page2 = require("pages/page2");
const Page3 = require("pages/page3");
let btbItemMessages = new TabBarItem();
btbItemMessages.title = "Messages";
btbItemMessages.icon = Image.createFromFile("images://messages.png");
btbItemMessages.badge.text = "1000";
btbItemMessages.badge.visible = true; //default false
if (parseInt(btbItemMessages.badge.text) > 99) {
btbItemMessages.badge.text = "99+";
}
const router = Router.of({
path: "/",
isRoot: true,
routes: [
BottomTabBarRouter.of({
path: "/btb",
to: "/btb/tab1/page1",
tabbarParams: () => ({
ios: { visible: false },
itemColor: {
normal: Color.BLACK,
selected: Color.WHITE
},
android: {
disableItemAnimation: true
},
backgroundColor: Color.create("#00A1F1")
}),
items: () => [{
title: "Profile",
icon: Image.createFromFile("images://user.png")
},
btbItemMessages,
{
title: "Settings",
icon: Image.createFromFile("images://setting.png")
}
],
// tab1
routes: [
// tab1
Route.of({
path: "/btb/tab1/page1",
build: (router, route) => {
return new Page1(router);
}
}),
// tab2
Route.of({
path: "/btb/tab2/page2",
build: (router, route) => {
return new Page2(router);
}
}),
// tab3
Route.of({
path: "/btb/tab3/page3",
build: (router, route) => {
return new Page3(router);
}
})
]
})
]
});
router.push("/btb");

Badge Position On iOS

On iOS, when BottomTabBarItem icon's size is big, badge can be positioned wrong by default. You should call move function for fix this problem.

BottomTabbar Animation On Android

On Android BottomTabbarItems animates when clicked but badge have no animation. In order to have a better experience disableItemAnimation can be used.