API Reference: UI.HeaderBar​
HeaderBar class represents Navigation Bar for iOS and Action Bar for Android. It is a bar shown on top of page under the statusBar object. You can use it for a way to navigate in the application or for certain functions with buttons. You can also show title of page on HeaderBar.
Creating an instance of HeaderBar class is not valid. You can access the header bar of a page via UI.Page.headerBar property.
On iOS, you should work with header bar in the scope of onLoad() and onShow() callbacks, otherwise behavior would be undefined.
​
TypeScript code blocks include examples of how to implement, override and components within the theme. You can create page with the UI Editor to make your page compatible with theming and then you can implement themable components programmatically. Once the page is created with the UI Editor, it generates a class under scripts/generated/pages. You can then extend that class with the following TypeScript classes.
When you hide the headerBar on iOS, page goes under the statusBar but Android it does not. This behaviour causes the difference between Android & iOS user interfaces. Giving paddingTop for IOS devices might help to solve this problem.
Basic HeaderBar
import PageSampleDesign from 'generated/pages/pageSample';import FlexLayout = require('sf-core/ui/flexlayout');import Application = require('sf-core/application');import System = require("sf-core/device/system");import HeaderBarItem = require('sf-core/ui/headerbaritem');import Color = require('sf-core/ui/color');​//You should create new Page from UI-Editor and extend with it.export default class Sample extends PageSampleDesign {​myItem: HeaderBarItem;​constructor() {super();// Overrides super.onShow methodthis.onShow = onShow.bind(this, this.onShow.bind(this));// Overrides super.onLoad methodthis.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) {const { headerBar } = System.OS === "Android" ? this : this.parentController;superOnShow();Application.statusBar.visible = false;headerBar.visible = true;}​/*** @event onLoad* This event is called once when page is created.* @param {function} superOnLoad super onLoad function*/function onLoad(superOnLoad: () => void) {superOnLoad();​const { headerBar } = System.OS === "Android" ? this : this.parentController;​headerBar.backgroundColor = Color.create("#00A1F1");headerBar.title = "Header Bar";// Border visibility is optionalheaderBar.borderVisibility = true;​this.myItem = new HeaderBarItem({title: "Done",onPress: function () {console.log("You pressed Done item!");}});this.headerBar.setItems([this.myItem]);}
const Page = require("sf-core/ui/page");const extend = require("js-base/core/extend");const HeaderBarItem = require('sf-core/ui/headerbaritem');const Color = require('sf-core/ui/color');const Application = require('sf-core/application');​var Page1 = extend(Page)(function(_super) {_super(this, {onLoad: function() {this.headerBar.backgroundColor = Color.create("#00A1F1");this.headerBar.title = "Header Bar";​// Border visibility is optionalthis.headerBar.borderVisibility = true;​var myItem = new HeaderBarItem({title: "Done",onPress: function() {console.log("You pressed Done item!");}});this.headerBar.setItems([myItem]);},onShow: function(params) {Application.statusBar.visible = false;this.headerBar.visible = true;}});});​module.exports = Page1;
​​
​
​
There is a default left item on the every HeaderBar. This default button is used to go back in the Router or Navigator history. The back action using this does not send any arguments to the previous page (this cannot be changed). This default behavior can be prevented by:
setting a custom left item
page.headerBar.leftItemEnabled = false
With the default behavior, iOS gesture to swipe back works. If one of the actions described above is used, this also prevents the default swipe back gesture.
For Android, on each page, the developer has to write custom back button action.
Since sf-core 3.0.0 it is possible to show a badge number or text with the HeaderBarItem. The badge has a circular or elliptical background, displayed on top-right to the HeaderBarItem. Most common use of the badge is to show the number of notifications or items that user needs to pay attention to. The text of the badge is manually managed by the developer. Basic properties of badge:
If the text length of the badge is less, it looks like a circle; otherwise, its width will extend to be an ellipse
The width of the badge may not extend the HeaderBarItem width, the larger text will be cut
The height of the badge is fixed, does not change
By default, it has a red background with white text
Font and colors of the badge can be changed via JavaScript code, themes cannot be used
​
import PageSampleDesign from 'generated/pages/pageSample';import FlexLayout = require('sf-core/ui/flexlayout');import Application = require('sf-core/application');import System = require("sf-core/device/system");import HeaderBarItem = require('sf-core/ui/headerbaritem');import ActivityIndicator = require('sf-core/ui/activityindicator');import addChild from "@smartface/contx/lib/smartface/action/addChild";import Color = require('sf-core/ui/color');​​//You should create new Page from UI-Editor and extend with it.export default class Sample extends PageSampleDesign {​itemContainerFl: FlexLayout;myActivityIndicator: ActivityIndicator;indicatorItem: HeaderBarItem;itemWithBadge: HeaderBarItem;​constructor() {super();// Overrides super.onShow methodthis.onShow = onShow.bind(this, this.onShow.bind(this));// Overrides super.onLoad methodthis.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) {const { headerBar } = this;superOnShow();Application.statusBar.visible = true;headerBar.visible = true;}​/*** @event onLoad* This event is called once when page is created.* @param {function} superOnLoad super onLoad function*/function onLoad(superOnLoad: () => void) {superOnLoad();const { headerBar } = this;​headerBar.title = "Smartface";headerBar.dispatch({type: "updateUserStyle",userStyle: {backgroundColor: "#FFFFFF",titleColor: "#000000"}});​this.itemContainerFl = new FlexLayout();this.dispatch(addChild(`itemContainerFl`, this.itemContainerFl, ".sf-flexLayout", {height: 50,width: 50,flexProps: {justifyContent: "CENTER",alignItems: "CENTER"}}));​this.myActivityIndicator = new ActivityIndicator();//@ts-ignorethis.myActivityIndicator.ios.activityIndicatorViewStyle = ActivityIndicator.iOS.ActivityIndicatorViewStyle.NORMAL;//@ts-ignorethis.itemContainerFl.addChild(this.myActivityIndicator, "myActivityIndicator", ".sf-activityIndicator", {height: 35,width: 35,color: "#00A1F1"});​this.indicatorItem = new HeaderBarItem({customView: this.itemContainerFl});​this.itemWithBadge = new HeaderBarItem({color: Color.BLUE,android: {systemIcon: 17301545 // OR 'ic_dialog_email'},ios: {systemItem: HeaderBarItem.iOS.SystemItem.BOOKMARKS},onPress: (): void => {headerBar.setItems([this.indicatorItem]);}});headerBar.setItems([this.itemWithBadge]);​this.itemWithBadge.badge.visible = true;this.itemWithBadge.badge.text = "7";}
const Page = require("sf-core/ui/page");const extend = require("js-base/core/extend");const HeaderBarItem = require('sf-core/ui/headerbaritem');const Color = require('sf-core/ui/color');const Application = require('sf-core/application');const ActivityIndicator = require('sf-core/ui/activityindicator');const FlexLayout = require('sf-core/ui/flexlayout');​var Page1 = extend(Page)(function (_super) {_super(this, {onLoad: function () {const page = this;page.headerBar.title = "Smartface";page.headerBar.backgroundColor = Color.WHITE;page.headerBar.titleColor = Color.BLACK;​let itemContainerFl = new FlexLayout({height: 50,width: 50,justifyContent: FlexLayout.JustifyContent.CENTER,alignItems: FlexLayout.AlignItems.CENTER});​let myActivityIndicator = new ActivityIndicator({height: 35,width: 35,color: Color.create("#00A1F1")});myActivityIndicator.ios.activityIndicatorViewStyle = ActivityIndicator.iOS.ActivityIndicatorViewStyle.NORMAL;itemContainerFl.addChild(myActivityIndicator);​let indicatorItem = new HeaderBarItem({customView: itemContainerFl});​let itemWithBadge = new HeaderBarItem({android: {systemIcon: 17301545 // OR 'ic_dialog_email'},ios: {systemItem: HeaderBarItem.iOS.SystemItem.BOOKMARKS},onPress: function () {page.headerBar.setItems([indicatorItem]);}});page.headerBar.setItems([itemWithBadge]);​itemWithBadge.badge.visible = true;itemWithBadge.badge.text = "7";},onShow: function (params) {Application.statusBar.visible = false;this.headerBar.visible = true;}});});​module.exports = Page1;
​​
​
You can wrap your design with a FlexLayout and set that layout to HeaderBar's titleLayout.
Title Layout can be used when developer wants to set an ImageView at HeaderBar.
When using titleLayout together with rotatable pages by setting orientation to AUTO, you should consider different Android and iOS behaviors.
​
When using it on iOS, you should consider that onOrientationChange event is fired before the change occurs, therefore you should do your resize calculations with care, by using other methods such as timeout.
On Android, the calculations are mostly done by context, therefore keep your calculations to iOS specific.
import PageSampleDesign from 'generated/pages/pageSample';import FlexLayout = require('sf-core/ui/flexlayout');import Application = require('sf-core/application');import HeaderBarItem = require('sf-core/ui/headerbaritem');import addChild from "@smartface/contx/lib/smartface/action/addChild";import Color = require('sf-core/ui/color');import Image = require("sf-core/ui/image");import ImageView = require("sf-core/ui/imageview");​//You should create new Page from UI-Editor and extend with it.export default class Sample extends PageSampleDesign {​myFlexLayout: FlexLayout;myImageView: Image;myItem: HeaderBarItem;leftItem: HeaderBarItem;​constructor() {super();// Overrides super.onShow methodthis.onShow = onShow.bind(this, this.onShow.bind(this));// Overrides super.onLoad methodthis.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) {const { headerBar } = this;superOnShow();Application.statusBar.visible = true;headerBar.visible = true;}​/*** @event onLoad* This event is called once when page is created.* @param {function} superOnLoad super onLoad function*/function onLoad(superOnLoad: () => void) {superOnLoad();const { headerBar } = this;this.myItem = new HeaderBarItem({title: "Done",color: Color.BLACK,onPress: function () {console.log("You pressed Done item!");}});this.headerBar.setItems([this.myItem]);​this.leftItem = new HeaderBarItem();this.leftItem.title = "Left";this.leftItem.color = Color.BLACK;this.headerBar.setLeftItem(this.leftItem);​​this.myFlexLayout = new FlexLayout();this.dispatch(addChild(`myFlexLayout`, this.myFlexLayout, ".sf-flexLayout", {width: 250,height: 50,backgroundColor: "#000000",flexProps: {justifyContent: "CENTER"}}));​this.myImageView = new ImageView({image: Image.createFromFile("images://icon.png")});​this.myFlexLayout.addChild(this.myImageView, "myImageView", ".sf-imageView", {width: 30,height: 30,backgroundColor: "#000000",imageFillType: "ASPECTFIT"});​this.headerBar.title = "";this.headerBar.titleLayout = this.myFlexLayout;}
const HeaderBarItem = require("sf-core/ui/headerbaritem");const FlexLayout = require("sf-core/ui/flexlayout");const Image = require("sf-core/ui/image");const ImageView = require("sf-core/ui/imageview");const Page = require("sf-core/ui/page");const extend = require("js-base/core/extend");const Color = require('sf-core/ui/color');const OS = require('sf-core/device/system').OS;​var Page1 = extend(Page)(function(_super) {_super(this, {onLoad: function() {var myItem = new HeaderBarItem({title: "Done",color: Color.BLACK,onPress: function() {console.log("You pressed Done item!");}});this.headerBar.setItems([myItem]);var leftItem = new HeaderBarItem();leftItem.title = "Left";leftItem.color = Color.BLACK;this.headerBar.setLeftItem(leftItem);var deviceHeaderBar = OS === "Android" ? this.headerBar.height : this.parentController.headerBar.height;var myFlexLayout = new FlexLayout({width: 700,height: deviceHeaderBar,justifyContent: FlexLayout.JustifyContent.CENTER});myFlexLayout.backgroundColor = Color.BLUEvar image = new ImageView({image: Image.createFromFile("images://icon.png"),width: 30,height: 30,imageFillType: ImageView.FillType.ASPECTFIT,});myFlexLayout.addChild(image);myFlexLayout.applyLayout();this.headerBar.title = "";this.headerBar.titleLayout = myFlexLayout;},onShow: function(params) {this.headerBar.visible = true;}});});​module.exports = Page1;
​​
​
Pages may use large titles in the HeaderBar if desired.
prefersLargeTitles property of page's belonging navigator must be set in order to use large title feature.
/* globals lang */require("i18n/i18n.js"); // Generates global lang objectimport Application = require("sf-core/application");import { errorStackBySourceMap } from "error-by-sourcemap";import System = require("sf-core/device/system");// Set uncaught exception handler, all exceptions that are not caught will// trigger onUnhandledError callback.Application.onUnhandledError = function (e: UnhandledError) {const error = errorStackBySourceMap(e);alert({title: e.type || lang.applicationError,message: System.OS === "Android" ? error.stack : (e.message + "\n\n*" + error.stack)});};import "./theme";require("sf-extension-utils");const router = require("./routes");router.push("/pages/page1");​
const buildExtender = require("sf-extension-utils/lib/router/buildExtender");const {NativeRouter: Router,NativeStackRouter: StackRouter,Route} = require("@smartface/router");require("sf-extension-utils/lib/router/goBack"); // Implements onBackButtonPressedconst router = Router.of({path: "/",isRoot: true,routes: [StackRouter.of({path: "/pages",routes: [Route.of({path: "/pages/page1",build: buildExtender({ getPageClass: () => require("pages/page1").default, headerBarStyle: { visible: true } })}),Route.of({path: "/pages/page2",build: buildExtender({ getPageClass: () => require("pages/page2").default, headerBarStyle: { visible: true } })}),]})]});​export = router;​
import Page1Design from 'generated/pages/page1';const HeaderBarItem = require("sf-core/ui/headerbaritem");const Page = require('sf-core/ui/page');​export default class Page1 extends Page1Design {router: any;constructor() {super();this.onShow = onShow.bind(this, this.onShow.bind(this));this.onLoad = onLoad.bind(this, this.onLoad.bind(this));}}​function onShow(superOnShow) {superOnShow();}​function onLoad(superOnLoad) {superOnLoad();​var myItem = new HeaderBarItem({title: "Next",onPress: () => this.router.push("/pages/page2")});this.headerBar.setItems([myItem]);this.headerBar.title = "page1";this.headerBar.ios.largeTitleDisplayMode = Page.iOS.LargeTitleDisplayMode.ALWAYS;}​
import Page2Design from 'generated/pages/page2';const Page = require('sf-core/ui/page');​export default class Page2 extends Page2Design {constructor() {super();this.onShow = onShow.bind(this, this.onShow.bind(this));this.onLoad = onLoad.bind(this, this.onLoad.bind(this));}}​function onShow(superOnShow) {superOnShow();}​function onLoad(superOnLoad) {superOnLoad();this.headerBar.title = "page2";this.headerBar.ios.largeTitleDisplayMode = Page.iOS.LargeTitleDisplayMode.NEVER;}​​
According to Smartface Router some of headerBar properties are moved parentController. These properties must be set like page.parentController.headerBar.backgroundImage
. These are:
-backgroundImage
-transparent
-alpha
-titleColor
-visible
-itemColor
-backgroundColor
-height
-borderVisibility
-backIndicatorImage
// iOS only
-translucent
// iOS only