Safe Area

For Android devices that have Safe Area (bezel at the bottom of the screen), the property is always set to true.

Apple suggests that we do not to place any controls outside safe area hence in iOS 11 you have to obey safe area rules when you position views in iOS application. Ui editor supports this option.

Example

Assume you have a page with a MapView instance in it with following properties:

If SafeArea Enabled property of page is set on property panel, page will have extra padding values for safe area. Remember these values won't affect properties panel.

Info

  • If SafeArea Enabled is set, padding values calculated by safe area and values from theme are added.

  • For example, let's assume that SafeArea Enabled is set to true and paddingTop is set to 10 of page. And extra paddingTop comes from safe area as 20. Then page will be rendered as if it has paddingTop as 30. Same applies with other directions.

Absolute Components

Recall that, if children of page have positionType of ABSOLUTE, their position won't be affected by any padding values of page. So, designer must be aware of it.

Safe are disabled vs enabled (portrait)

Safe are disabled vs enabled (landscape)

Manually Handling SafeArea

By default, Smartface pages have their Orientation locked to PORTRAIT. Make sure to change that by Smartface UI Editor.

When you set safeAreaEnabled property to false, Smartface will not handle Safe area spaces and your layouts will overflow to safe area by default. If you have a specific scenario like:

  • You want to handle bottom safe area yourself but you want top safe handle to be handled by itself (or vice versa)

  • You want to handle safe area only on portrait mode (or vice versa)

In those cases, you should use onSafeAreaPaddingChange event to handle the safe area by yourself.

Notice that safeAreaEnabled property on Smartface Cloud IDE is set to false for examples below.

Page UI
Page Code
Page UI
.ui/pgSafeArea.pgx
{
"components": [
{
"className": ".sf-page",
"id": "7d09-48ed-cf7e-86f8",
"initialized": true,
"props": {
"children": [
"f030-2834-f60d-0ae5",
"d45b-9654-a121-f741",
"8d3e-bd0c-7634-f16d"
],
"isRemovable": true,
"name": "pgSafeArea",
"orientation": "AUTO",
"parent": null,
"safeAreaEnabled": false
},
"type": "Page",
"userProps": {
"flexProps": {
"justifyContent": "SPACE_BETWEEN",
"alignItems": "STRETCH"
},
"orientation": "AUTO",
"paddingBottom": 0,
"paddingLeft": 0,
"paddingRight": 0,
"paddingTop": 0,
"safeAreaEnabled": false
},
"version": "6.15.1"
},
{
"className": ".sf-statusBar",
"id": "f030-2834-f60d-0ae5",
"props": {
"children": [],
"isRemovable": false,
"name": "statusBar",
"parent": "7d09-48ed-cf7e-86f8"
},
"type": "StatusBar",
"userProps": {
"visible": true
}
},
{
"className": ".sf-headerBar",
"id": "d45b-9654-a121-f741",
"props": {
"children": [],
"isRemovable": false,
"name": "headerBar",
"parent": "7d09-48ed-cf7e-86f8",
"title": "Page1"
},
"type": "HeaderBar",
"userProps": {
"title": "Page1",
"visible": true
}
},
{
"className": ".sf-flexLayout",
"id": "8d3e-bd0c-7634-f16d",
"props": {
"children": [],
"name": "flexLayout1",
"parent": "7d09-48ed-cf7e-86f8"
},
"type": "FlexLayout",
"userProps": {
"backgroundColor": "rgba( 65, 117, 5, 1 )",
"flexProps": {
"flexGrow": 1
},
"marginTop": null,
"testId": "XL66eMwOv"
}
}
]
}
Page Code
scripts/pages/pgSafeArea.ts
import PgSafeAreaDesign from 'generated/pages/pgSafeArea';
import Screen from 'sf-core/device/screen';
import System from 'sf-core/device/system';
export default class PgSafeArea extends PgSafeAreaDesign {
constructor() {
super();
this.onShow = onShow.bind(this, this.onShow.bind(this));
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
this.orientation = PgSafeAreaDesign.Orientation.AUTO;
this.ios.onSafeAreaPaddingChange = (padding) => {
this.dispatch({
type: "updateUserStyle",
userStyle: {
paddingBottom: padding.bottom,
paddingLeft: padding.left,
paddingRight: padding.right,
paddingTop: padding.top
}
});
this.layout.applyLayout();
}
}
}
function onShow(superOnShow: () => void) {
superOnShow();
}
function onLoad(superOnLoad: () => void) {
superOnLoad();
}

Notice the edges and notice how page acts like safeAreaEnabled is set to true.

Changing SafeAreaEnabled Programmatically

If you don't want to handle safeArea with onSafeAreaPaddingChange but you also have a need to change the padding values runtime, you should use safeAreaLayoutMode property.

safeAreaLayoutMode works for iOS only. See the disclaimer above for Android.

For the page UI, the same page from example above was used.

import PgSafeAreaDesign from 'generated/pages/pgSafeArea';
import Screen from 'sf-core/device/screen';
import System from 'sf-core/device/system';
export default class PgSafeArea extends PgSafeAreaDesign {
constructor() {
super();
this.onShow = onShow.bind(this, this.onShow.bind(this));
this.onLoad = onLoad.bind(this, this.onLoad.bind(this));
this.orientation = PgSafeAreaDesign.Orientation.AUTO;
this.onOrientationChange = ({ orientation }) => {
/**
* Enable safearea handling if orientation is landscape(sideways)
*/
if (System.OS === System.OSType.ANDROID) {
return;
}
this.ios.safeAreaLayoutMode = orientation !== PgSafeAreaDesign.Orientation.PORTRAIT;
this.layout.applyLayout();
}
}
}
function onShow(superOnShow: () => void) {
superOnShow();
}
function onLoad(superOnLoad: () => void) {
superOnLoad();
}

Keep an eye on the edges, notice how they are filled.