Router
Since routing is very important for mobile applications, Smartface uses Smartface Router to provide many different useful features for easily navigating & communicating between different screens.
For more information on the router and detailed usages please see the router documentation.
https://smartface.github.io/router
Navigating to page and assigning routesCommon Features of Router
- Nested routes
- Route redirection
- Route blocking
- History listening
- NativeStackRouter
NativeStackRouter is providing for your app to move to different pages and hold their route history by keeping the latest pushed page on top of the stack. It resembles to Stack Navigator in react-native.
- Deeplinking
Basic Usage of push
- Router
- Page
import { NativeRouter, NativeStackRouter, Route } from '@smartface/router';
import Application from '@smartface/native/application';
import Page1 from 'pages/page1';
import Page2 from 'pages/page2';
import Page3 from 'pages/page3';
const router = NativeRouter.of({
path: '/',
isRoot: true,
routes: [
NativeStackRouter.of({
path: '/pages',
routes: [
Route.of<Page1>({
path: '/pages/page1',
build(router, route) {
return new Page1(router,route);
}
}),
Route.of<Page2>({
path: '/pages/page2',
build(router, route) {
return new Page2(router,route);
}
})
]
})
]
});
export default router;
import Page1Design from 'generated/pages/page1';
import PageTitleLayout from 'components/PageTitleLayout';
import System from '@smartface/native/device/system';
import Label from '@smartface/native/ui/label';
import { Route, Router } from '@smartface/router';
import { styleableComponentMixin } from '@smartface/styling-context';
class StyleableLabel extends styleableComponentMixin(Label) {}
export default class Page1 extends Page1Design {
private disposeables: (() => void)[] = [];
constructor(private router?: Router, private route?: Route) {
super({});
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
*/
onShow() {
super.onShow();
this.disposeables.push(
this.btnNext.on('press', () => {
this.router.push('page2', { message: 'Hello World!' });
})
);
}
/**
* @event onLoad
* This event is called once when page is created.
*/
onLoad() {
super.onLoad();
}
onHide(): void {
this.dispose();
}
dispose(): void {
this.disposeables.forEach((item) => item());
}
}
Basic Usage of modal page
You can use modal page to show a page on top of the current page. For modal page, you can use the modal
property in the route definition.
NativeStackRouter.of({
path: '/pages/page3',
to: '/pages/page3/main',
modal: true,
routes: [
Route.of<Page3>({
path: '/pages/page3/main',
build(router, route) {
return new Page3(router, route);
}
})
]
})
- Router
- Page2
- Page3 (Modal Page)
import { NativeRouter, NativeStackRouter, Route } from '@smartface/router';
import Application from '@smartface/native/application';
import Page1 from 'pages/page1';
import Page2 from 'pages/page2';
import Page3 from 'pages/page3';
const router = NativeRouter.of({
path: '/',
isRoot: true,
routes: [
NativeStackRouter.of({
path: '/pages',
routes: [
Route.of<Page1>({
path: '/pages/page1',
build(router, route) {
return new Page1(router,route);
}
}),
Route.of<Page2>({
path: '/pages/page2',
build(router, route) {
return new Page2(router,route);
}
}),
NativeStackRouter.of({
path: '/pages/page3',
to: '/pages/page3/main',
modal: true,
routes: [
Route.of<Page3>({
path: '/pages/page3/main',
build(router, route) {
return new Page3(router, route);
}
})
]
})
]
})
]
});
export default router;
import Page2Design from 'generated/pages/page2';
import HeaderBarItem from '@smartface/native/ui/headerbaritem';
import PageTitleLayout from 'components/PageTitleLayout';
import HeaderBar from '@smartface/native/ui/headerbar';
import { Router, Route } from '@smartface/router';
import { withDismissAndBackButton } from '@smartface/mixins';
import Color from '@smartface/native/ui/color';
export default class Page2 extends withDismissAndBackButton(Page2Design) {
routeData: Record<string, any> = this.route.getState().routeData;
parentController: any;
private disposeables: (() => void)[] = [];
constructor(private router?: Router, private route?: Route) {
super({});
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
*/
onShow() {
super.onShow();
this.headerBar.leftItemEnabled = false;
this.initDismissButton(this.router);
this.initBackButton(this.router);
this.routeData && console.info(this.routeData.message);
this.disposeables.push(this.btnOpenModal.on('press', () => this.router.push('page3')));
}
/**
* @event onLoad
* This event is called once when page is created.
*/
onLoad() {
super.onLoad();
}
onHide(): void {
this.dispose();
}
dispose(): void {
this.disposeables.forEach((item) => item());
}
}
import Page3Design from 'generated/pages/page3';
import { Route, Router } from '@smartface/router';
import { withDismissAndBackButton } from '@smartface/mixins';
export default class Page3 extends withDismissAndBackButton(Page3Design) {
private disposeables: (() => void)[] = [];
routeData: Record<string, any> = this.route.getState().routeData;
parentController: any;
constructor(private router?: Router, private route?: Route) {
super({});
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
*/
onShow() {
super.onShow();
this.initBackButton(this.router);
this.initDismissButton(this.router);
this.disposeables.push(this.btnDismiss.on('press', () => this.router.goBack()));
}
/**
* @event onLoad
* This event is called once when page is created.
*/
onLoad() {
super.onLoad();
}
onHide(): void {
this.dispose();
}
dispose(): void {
this.disposeables.forEach((item) => item());
}
}}
Bottom Sheet
Bottom sheet helps people perform a distinct task that’s related to the parent view without taking them away from their current context.
There is differences between Android and iOS. On iOS the bottom sheet uses a Page to display the content. On Android, the bottom sheet uses a View to display the content.
iOS
Example route for bottom sheet:
NativeStackRouter.of({
path: '/pages/bottomSheet',
to: '/pages/bottomSheet/page',
modal: true,
modalType: 'bottom-sheet',
bottomSheetOptions: {
cornerRadius: 20,
detents: ['large', 'medium'],
isGrabberVisible: true
},
routes: [
Route.of({
path: `/pages/bottomSheet/page`,
build: (router, route) => new PgModalBottomSheet(router, route)
})
]
}),
- Router
- Page
- Bottom Sheet
import { NativeRouter, NativeStackRouter, Route } from '@smartface/router';
import Application from '@smartface/native/application';
import Page1 from 'pages/page1';
import Page2 from 'pages/page2';
import Page3 from 'pages/page3';
import PgModalBottomSheet from 'pages/pgModalBottomSheet';
Application.on('backButtonPressed', () => {
NativeRouter.getActiveRouter()?.goBack();
});
const router = NativeRouter.of({
path: '/',
isRoot: true,
routes: [
NativeStackRouter.of({
path: '/pages',
routes: [
Route.of<Page1>({
path: '/pages/page1',
build(router, route) {
return new Page1(router,route);
}
}),
Route.of<Page2>({
path: '/pages/page2',
build(router, route) {
return new Page2(router,route);
}
}),
NativeStackRouter.of({
path: '/pages/page3',
to: '/pages/page3/main',
modal: true,
routes: [
Route.of<Page3>({
path: '/pages/page3/main',
build(router, route) {
return new Page3(router, route);
}
})
]
}),
NativeStackRouter.of({
path: '/pages/bottomSheet',
to: '/pages/bottomSheet/page',
modal: true,
modalType: 'bottom-sheet',
bottomSheetOptions: {
cornerRadius: 20,
detents: ['large', 'medium'],
isGrabberVisible: true
},
routes: [
Route.of({
path: `/pages/bottomSheet/page`,
build: (router, route) => new PgModalBottomSheet(router, route)
})
]
}),
]
})
]
});
export default router;
import Page2Design from 'generated/pages/page2';
import HeaderBarItem from '@smartface/native/ui/headerbaritem';
import PageTitleLayout from 'components/PageTitleLayout';
import HeaderBar from '@smartface/native/ui/headerbar';
import { Router, Route } from '@smartface/router';
import { withDismissAndBackButton } from '@smartface/mixins';
import Color from '@smartface/native/ui/color';
export default class Page2 extends withDismissAndBackButton(Page2Design) {
routeData: Record<string, any> = this.route.getState().routeData;
parentController: any;
private disposeables: (() => void)[] = [];
constructor(private router?: Router, private route?: Route) {
super({});
}
/**
* @event onShow
* This event is called when a page appears on the screen (everytime).
*/
onShow() {
super.onShow();
this.headerBar.leftItemEnabled = false;
this.initDismissButton(this.router);
this.initBackButton(this.router);
this.routeData && console.info(this.routeData.message);
this.disposeables.push(this.btnOpenModal.on('press', () => this.router.push('page3')));
this.disposeables.push(this.btnBottomSheet.on('press', () => this.router.push('bottomSheet')));
}
/**
* @event onLoad
* This event is called once when page is created.
*/
onLoad() {
super.onLoad();
}
onHide(): void {
this.dispose();
}
dispose(): void {
this.disposeables.forEach((item) => item());
}
}
import PgModalBottomSheetDesign from 'generated/pages/pgModalBottomSheet';
import { withDismissAndBackButton } from '@smartface/mixins';
import { Router, Route } from '@smartface/router';
export default class PgModalBottomSheet extends withDismissAndBackButton(PgModalBottomSheetDesign) {
constructor(private router?: Router, private route?: Route) {
super({});
}
/**
* @event onShow
* This event is called when the page appears on the screen (everytime).
*/
onShow() {
super.onShow();
this.initBackButton(this.router); //Addes a back button to the page headerbar.
}
/**
* @event onLoad
* This event is called once when the page is created.
*/
onLoad() {
super.onLoad();
}
}}
Android
On Android, the bottom sheet is a modal dialog that slides up from the bottom of the screen. It is a good choice for displaying a list of options or actions.
First, you need to create your custom component in library then you can use it in your Bottom Sheet.
import PgModalBottomSheetDesign from 'generated/pages/pgModalBottomSheet';
import { withDismissAndBackButton } from '@smartface/mixins';
import { Router, Route } from '@smartface/router';
import BottomSheet from '@smartface/native/ui/bottomsheet';
import bottomSheetFlex from 'components/BottomSheetFlex';
import { themeService } from 'theme';
export default class PgModalBottomSheet extends withDismissAndBackButton(PgModalBottomSheetDesign) {
myBottomSheet: BottomSheet;
constructor(private router?: Router, private route?: Route) {
super({});
}
createBox() {
// BottomSheetFlex is a custom component that is created for the bottom sheet.
const content = new bottomSheetFlex();
themeService.addGlobalComponent(content, 'bottomSheetComponent');
return content;
}
initBottomSheet() {
this.myBottomSheet = new BottomSheet({
view: this.createBox(),
borderRadius: 10,
detents: ['medium']
});
}
/**
* @event onShow
* This event is called when the page appears on the screen (everytime).
*/
onShow() {
super.onShow();
this.initBackButton(this.router); //Addes a back button to the page headerbar.
}
/**
* @event onLoad
* This event is called once when the page is created.
*/
onLoad() {
super.onLoad();
this.initBottomSheet();
}
}
If you want to use Listview and Gridview in your Bottom Sheet, you need to set nestedScrollingEnabled property to true
.