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.
On Android side, you can not add more than five tab bar items to bottom tab bar.
Create 3 different page from UI editor named like
- pgProfile
- pgMessages
- pgSettings
and export them from the pages/index.ts file
The components in the example are added from the code for better showcase purposes. To learn more about the subject you can refer to:
Adding Component From CodeAs a best practice, Smartface recommends using the WYSIWYG editor in order to add components and styles to your page or library. To learn how to use UI Editor better, please refer to this documentation
UI Editor Basics- scripts/start.ts
- scripts/routes/index.ts
- scripts/routes/tabbar.ts
- scripts/pages/pgProfile.ts
- scripts/pages/pgMessages.ts
- scripts/pages/pgSettings.ts
import "@smartface/extension-utils";
import "theme";
import router from "routes";
router.push("/btb");
import { NativeRouter } from '@smartface/router';
import Application from '@smartface/native/application';
import TabbarRoute from './tabbar';
Application.on('backButtonPressed', () => {
NativeRouter.getActiveRouter()?.goBack();
});
const router = NativeRouter.of({
path: '/',
isRoot: true,
routes: [TabbarRoute]
});
export default router;
import { BottomTabBarRouter, NativeStackRouter, Route, NativeRouter } from '@smartface/router';
import Color from '@smartface/native/ui/color';
import * as Pages from 'pages';
import Image from '@smartface/native/ui/image';
const bottomTabBarRouter = BottomTabBarRouter.of({
path: '/btb',
to: '/btb/tab1/page1',
homeRoute: 0,
tabbarParams: () => ({
ios: { translucent: 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
NativeStackRouter.of({
path: '/btb/tab1',
to: '/btb/tab1/page1',
routes: [
Route.of<Pages.Page1>({
path: `/btb/tab1/page1`,
build(router, route) {
return new Pages.Page1(router, route);
},
headerBarParams: () => ({
visible: true
})
})
]
}),
NativeStackRouter.of({
path: '/btb/tab2',
to: '/btb/tab2/page2',
routes: [
Route.of<Pages.Page2>({
path: `/btb/tab1/page2`,
build(router, route) {
return new Pages.Page2(router, route);
},
headerBarParams: () => ({
visible: true
})
})
]
}),
NativeStackRouter.of({
path: '/btb/tab3',
to: '/btb/tab3/page3',
routes: [
Route.of<Pages.Page3>({
path: `/btb/tab3/page3`,
build(router, route) {
return new Pages.Page3(router, route);
},
headerBarParams: () => ({
visible: true
})
})
]
})
]
});
export default bottomTabBarRouter;
import PgProfileDesign from 'generated/pages/pgProfile';
import Label from '@smartface/native/ui/label';
import { Route, Router } from '@smartface/router';
import { styleableComponentMixin } from '@smartface/styling-context';
class StyleableLabel extends styleableComponentMixin(Label) {}
//You should create new Page from UI-Editor and extend with it.
export default class PgProfile extends PgProfileDesign {
lbl: StyleableLabel;
constructor(private router?: Router, private route?: Route) {
super({});
}
onShow() {
super.onShow();
}
onLoad() {
super.onLoad();
this.lbl = new StyleableLabel({
text: 'Profile'
});
this.addChild(this.lbl, `lbl`, '.sf-label', (userProps) => {
userProps.textColor = '#808080';
userProps.font = {
size: 20,
bold: true,
italic: false,
family: 'Arial',
style: 'Semibold'
};
return userProps;
});
}
}
import PgMessagesDesign from 'generated/pages/pgMessages';
import Label from '@smartface/native/ui/label';
import { Route, Router } from '@smartface/router';
import { styleableComponentMixin } from '@smartface/styling-context';
class StyleableLabel extends styleableComponentMixin(Label) {}
//You should create new Page from UI-Editor and extend with it.
export default class PgMessages extends PgMessagesDesign {
lbl: StyleableLabel;
constructor(private router?: Router, private route?: Route) {
super({});
}
onShow() {
super.onShow();
}
onLoad() {
super.onLoad();
this.lbl = new StyleableLabel({
text: 'Messages'
});
this.addChild(this.lbl, `lbl`, '.sf-label', (userProps) => {
userProps.textColor = '#808080';
userProps.font = {
size: 20,
bold: true,
italic: false,
family: 'Arial',
style: 'Semibold'
};
return userProps;
});
}
}
import PgSettingsDesign from 'generated/pages/pgSettings';
import Label from '@smartface/native/ui/label';
import { Route, Router } from '@smartface/router';
import { styleableComponentMixin } from '@smartface/styling-context';
class StyleableLabel extends styleableComponentMixin(Label) {}
//You should create new Page from UI-Editor and extend with it.
export default class PgSettings extends PgSettingsDesign {
lbl: StyleableLabel;
constructor(private router?: Router, private route?: Route) {
super({});
}
onShow() {
super.onShow();
}
onLoad() {
super.onLoad();
this.lbl = new StyleableLabel({
text: 'Settings'
});
this.addChild(this.lbl, `lbl`, '.sf-label', (userProps) => {
userProps.textColor = '#808080';
userProps.font = {
size: 20,
bold: true,
italic: false,
family: 'Arial',
style: 'Semibold'
};
return userProps;
});
}
}
Please check this guideline before choosing your custom TabBarItem icons.
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/start.ts
- scripts/routes/index.ts
import "@smartface/extension-utils";
import "theme";
import router from "routes";
router.push("/btb");
import Image from '@smartface/native/ui/image';
import { BottomTabBarRouter, NativeStackRouter, Route, NativeRouter } from '@smartface/router';
import Color from '@smartface/native/ui/color';
import * as Pages from 'pages';
import TabBarItem from '@smartface/native/ui/tabbaritem';
let btbItemMessages = new TabBarItem();
btbItemMessages.title = 'Tab2';
btbItemMessages.badge.text = '1000';
btbItemMessages.badge.visible = true; // default false
if (parseInt(btbItemMessages.badge.text) > 99) {
btbItemMessages.badge.text = '99+';
}
const router = NativeRouter.of({
path: '/',
isRoot: true,
routes: [
BottomTabBarRouter.of({
path: '/btb',
to: '/btb/tab1/page1',
tabbarParams: () => ({
ios: { translucent: 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<Pages.Page1>({
path: `btb/tab1/page1`,
build(router, route) {
return new Pages.Page1(router, route);
},
headerBarParams: () => ({
visible: true
})
}),
// tab2
Route.of<Pages.Page2>({
path: `btb/tab1/page2`,
build(router, route) {
return new Pages.Page2(router, route);
},
headerBarParams: () => ({
visible: true
})
}),
// tab3
Route.of<Pages.Page3>({
path: `btb/tab1/page3`,
build(router, route) {
return new Pages.Page3(router, route);
},
headerBarParams: () => ({
visible: true
})
})
]
})
]
});
export default router;
BottomTabBar Font Change
- scripts/routes/tabbar.ts
- HeaderBar Style Json
import { BottomTabBarRouter, NativeStackRouter, Route, NativeRouter } from '@smartface/router';
import Color from '@smartface/native/ui/color';
import * as Pages from 'pages';
import Image from '@smartface/native/ui/image';
import { themeService } from 'theme';
import TabBarItem from '@smartface/native/ui/tabbaritem';
import System from '@smartface/native/device/system';
import AttributedString from '@smartface/native/global/attributedstring';
const tabbarFont = themeService.getNativeStyle('.sf-headerBar').font;
const setBtbItems = () => {
const BtbItems = [];
btbItems.forEach((item) => {
let title = { title: item.title }
let icon = { icon: Image.createFromFile(`${item.icon}`) }
let btbItemProperties = { ...title, ...icon };
const btbItem = new TabBarItem(btbItemProperties);
if (System.OS === System.OSType.ANDROID) {
btbItem.android.attributedTitle = new AttributedString({
string: item.title,
font: tabbarFont
});
} else {
btbItem.ios.font = tabbarFont;
}
BtbItems.push(btbItem);
});
return BtbItems;
};
const btbItems = [
{
title: 'Profiles',
icon: 'images://profile.png'
},
{
title: 'Messages',
icon: 'images://messages.png'
},
{
title: 'Settings',
icon: 'images://settings.png'
}
];
const bottomTabBarRouter = BottomTabBarRouter.of({
path: '/btb',
to: '/btb/tab1/page1',
homeRoute: 0,
tabbarParams: () => ({
ios: { translucent: false },
itemColor: {
normal: Color.BLACK,
selected: Color.WHITE
},
backgroundColor: Color.create('#00A1F1')
}),
items: setBtbItems(),
// tab1
routes: [
// tab1
NativeStackRouter.of({
path: '/btb/tab1',
to: '/btb/tab1/page1',
routes: [
Route.of<Pages.Page1>({
path: `/btb/tab1/page1`,
build(router, route) {
return new Pages.Page1(router, route);
},
headerBarParams: () => ({
visible: true
})
})
]
}),
NativeStackRouter.of({
path: '/btb/tab2',
to: '/btb/tab2/page2',
routes: [
Route.of<Pages.Page2>({
path: `/btb/tab1/page2`,
build(router, route) {
return new Pages.Page2(router, route);
},
headerBarParams: () => ({
visible: true
})
})
]
}),
NativeStackRouter.of({
path: '/btb/tab3',
to: '/btb/tab3/page3',
routes: [
Route.of<Pages.Page3>({
path: `/btb/tab3/page3`,
build(router, route) {
return new Pages.Page3(router, route);
},
headerBarParams: () => ({
visible: true
})
})
]
})
]
});
export default bottomTabBarRouter;
{
".sf-headerBar": {
"masksToBounds": true,
"visible": true,
"backgroundColor": "#00a1f1",
"titleColor": "#ffffff",
"itemColor": "#ffffff",
"font": {
"size": 15,
"bold": false,
"italic": false,
"family": "ShortStack"
}
}
}
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.
On Android BottomTabbarItems animates when clicked but badge have no animation. In order to have a better experience disableItemAnimation can be used.