MapView

API Reference: UI.MapView

MapView is a view to display native maps (Apple Maps on iOS and Google Maps on Android).

Android Manifest

Smartface Android Emulator comes with its own Google Maps API-Keys. Before publishing your project, you must change that key from AndroidManifest.xml. Follow the guide to get a key.

Updating Android Manifest

  • Go to /config/Android/AndroidManifest.xml

  • Add the following code below under tag

AndroidManifest.xml
AndroidManifest.xml
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value=" ADD API-KEY HERE "
/>

Basic MapView

In this example, lazy loading is also enabled on Line#14. Note that this is Android only property. For more information please refer here.

TypeScript
JavaScript
TypeScript
import PageSampleDesign from 'generated/pages/pageSample';
import FlexLayout = require('sf-core/ui/flexlayout');
import Application = require('sf-core/application');
import MapView = require('sf-core/ui/mapview');
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 {
myMapView: MapView;
constructor() {
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) {
const { headerBar } = this;
superOnShow();
Application.statusBar.visible = false;
headerBar.visible = false;
// Enable lazy loading on Android
this.myMapView.android.prepareMap();
}
/**
* @event onLoad
* This event is called once when page is created.
* @param {function} superOnLoad super onLoad function
*/
function onLoad(superOnLoad: () => void) {
superOnLoad();
this.myMapView = new MapView({
scrollEnabled: true,
rotateEnabled: true,
zoomEnabled: true,
compassEnabled: true,
type: MapView.Type.NORMAL,
onCreate: (): void => {
const centerLocation = {
latitude: 37.4488259,
longitude: -122.1600047
};
this.myMapView.setCenterLocationWithZoomLevel(centerLocation, 11, false);
for (let i = 0; i < 10; i++) {
//@ts-ignore
let myPin = new MapView.Pin({
location: {
latitude: 37.4488259 + i * 0.01,
longitude: -122.1600047
},
title: 'Title ' + i,
subtitle: 'Subtitle',
color: Color.RED
});
myPin.onPress = function (index: number) {
console.log("Title : " + this.title);
};
this.myMapView.addPin(myPin);
}
}
});
this.layout.addChild(this.myMapView, "myMapView", ".sf-mapView", {
height: null,
left: 0,
top: 0,
right: 0,
bottom: 0,
flexProps: {
positionType: "ABSOLUTE"
}
});
}
JavaScript
const extend = require("js-base/core/extend");
const Page = require("sf-core/ui/page");
const MapView = require('sf-core/ui/mapview');
const Color = require('sf-core/ui/color');
const FlexLayout = require('sf-core/ui/flexlayout');
var Page1 = extend(Page)(
function(_super) {
_super(this, {
onShow: function(params) {
Application.statusBar.visible = false;
this.headerBar.visible = false;
// Enable lazy loading on Android
this.map.android.prepareMap();
},
onLoad: function() {
var myMapView = new MapView({
left: 0,
top: 0,
right: 0,
bottom: 0,
positionType: FlexLayout.PositionType.ABSOLUTE,
scrollEnabled: true,
rotateEnabled: true,
zoomEnabled: true,
compassEnabled: true,
type: MapView.Type.NORMAL,
onCreate: function() {
var centerLocation = {
latitude: 37.4488259,
longitude: -122.1600047
};
myMapView.setCenterLocationWithZoomLevel(centerLocation,11,false); //Added in Release 6.11.0 & old usage is deprecated.
for (var i = 0; i < 10; i++) {
var myPin = new MapView.Pin({
location: {
latitude: 37.4488259 + i * 0.01,
longitude: -122.1600047
},
title: 'Title ' + i,
subtitle: 'Subtitle',
color: Color.RED
});
myPin.onPress = function(index) {
console.log("Title : " + this.title);
};
myMapView.addPin(myPin);
}
}
});
this.map = myMapView;
this.layout.addChild(myMapView);
}
});
}
);
module.exports = Page1;

MapView with Cluster

Cluster that groups two or more distinct pins into a single entity. Cluster works on Android & iOS 11.0+.

TypeScript
JavaScript
TypeScript
import PageSampleDesign from 'generated/pages/pageSample';
import FlexLayout = require('sf-core/ui/flexlayout');
import Application = require('sf-core/application');
import MapView = require('sf-core/ui/mapview');
import Color = require('sf-core/ui/color');
import Font = require('sf-core/ui/font');
type locationType = { latitude: number, longitude: number };
//You should create new Page from UI-Editor and extend with it.
export default class Sample extends PageSampleDesign {
myMapView: MapView;
constructor() {
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;
}
averageGeolocation(pins: MapView.Pin[]): locationType {
if (pins.length === 1) {
return pins[0].location;
}
let x = 0.0;
let y = 0.0;
let z = 0.0;
for (let pin of pins) {
let latitude = pin.location.latitude * Math.PI / 180;
let longitude = pin.location.longitude * Math.PI / 180;
x += Math.cos(latitude) * Math.cos(longitude);
y += Math.cos(latitude) * Math.sin(longitude);
z += Math.sin(latitude);
}
let total = pins.length;
x = x / total;
y = y / total;
z = z / total;
let centralLongitude = Math.atan2(y, x);
let centralSquareRoot = Math.sqrt(x * x + y * y);
let centralLatitude = Math.atan2(z, centralSquareRoot);
return {
latitude: centralLatitude * 180 / Math.PI,
longitude: centralLongitude * 180 / Math.PI
};
}
}
/**
* @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 = false;
headerBar.visible = false;
// Enable lazy loading on Android
this.myMapView.android.prepareMap();
}
/**
* @event onLoad
* This event is called once when page is created.
* @param {function} superOnLoad super onLoad function
*/
function onLoad(superOnLoad: () => void) {
superOnLoad();
this.myMapView = new MapView({
flexGrow: 1,
onCreate: () => {
let centerLocation = {
latitude: 37.4488259,
longitude: -122.1600047
};
this.myMapView.setCenterLocationWithZoomLevel(centerLocation, 12, false);
for (let i = 0; i < 10; i++) {
//@ts-ignore
let myPin = new MapView.Pin({
location: {
latitude: 37.4488259 + i * 0.01,
longitude: -122.1600047
},
title: 'Title ' + i,
subtitle: 'Subtitle',
color: Color.RED
});
myPin.onPress = function (index) {
console.log("Title : " + this.title);
};
this.myMapView.addPin(myPin);
}
}
});
this.myMapView.clusterEnabled = true;
this.myMapView.clusterFillColor = Color.RED;
this.myMapView.clusterBorderColor = Color.WHITE;
this.myMapView.ios.clusterBorderWidth = 3;
this.myMapView.clusterTextColor = Color.WHITE;
this.myMapView.clusterFont = Font.create(Font.DEFAULT, 20, Font.BOLD);
this.myMapView.ios.clusterPadding = 15;
this.myMapView.onClusterPress = (pins: MapView.Pin[]) => {
var centerLocation = this.averageGeolocation(pins);
this.myMapView.setCenterLocationWithZoomLevel(centerLocation, 12, true);
};
this.layout.addChild(this.myMapView, "myMapView", ".sf-mapView", {
height: null,
left: 0,
top: 0,
right: 0,
bottom: 0,
flexProps: {
positionType: "ABSOLUTE"
}
});
}
JavaScript
const extend = require("js-base/core/extend");
const Page = require("sf-core/ui/page");
const MapView = require('sf-core/ui/mapview');
const Color = require('sf-core/ui/color');
const Font = require('sf-core/ui/font');
var Page1 = extend(Page)(
function(_super) {
_super(this, {
onShow: function(params) {
Application.statusBar.visible = false;
this.headerBar.visible = false;
this["myMapView"].android.prepareMap();
},onLoad: function(){
var myMapView = new MapView({
flexGrow: 1,
onCreate: function() {
var centerLocation = {
latitude: 37.4488259,
longitude: -122.1600047
};
myMapView.setCenterLocationWithZoomLevel(centerLocation,12,false);
for (var i = 0; i < 10; i++) {
var myPin = new MapView.Pin({
location: {
latitude: 37.4488259 + i * 0.01,
longitude: -122.1600047
},
title: 'Title ' + i,
subtitle: 'Subtitle',
color: Color.RED
});
myPin.onPress = function(index) {
console.log("Title : " + this.title);
};
myMapView.addPin(myPin);
}
}
});
myMapView.clusterEnabled = true;
myMapView.clusterFillColor = Color.RED;
myMapView.clusterBorderColor = Color.WHITE;
myMapView.ios.clusterBorderWidth = 3;
myMapView.clusterTextColor = Color.WHITE;
myMapView.clusterFont = Font.create(Font.DEFAULT, 20, Font.BOLD);
myMapView.ios.clusterPadding = 15;
myMapView.onClusterPress = function(pins){
var centerLocation = averageGeolocation(pins);
myMapView.setCenterLocationWithZoomLevel(centerLocation,12,true);
};
function averageGeolocation(pins) {
if (pins.length === 1) {
return pins[0].location;
}
let x = 0.0;
let y = 0.0;
let z = 0.0;
for (let pin of pins) {
let latitude = pin.location.latitude * Math.PI / 180;
let longitude = pin.location.longitude * Math.PI / 180;
x += Math.cos(latitude) * Math.cos(longitude);
y += Math.cos(latitude) * Math.sin(longitude);
z += Math.sin(latitude);
}
let total = pins.length;
x = x / total;
y = y / total;
z = z / total;
let centralLongitude = Math.atan2(y, x);
let centralSquareRoot = Math.sqrt(x * x + y * y);
let centralLatitude = Math.atan2(z, centralSquareRoot);
return {
latitude: centralLatitude * 180 / Math.PI,
longitude: centralLongitude * 180 / Math.PI
};
}
this["myMapView"] = myMapView;
this.layout.addChild(myMapView);
}
});
}
);
module.exports = Page1;

Removing all pins at once

Developers don't need to store all pins remove them later.

This can be handled by calling myMap.removeAllPins();

Adding pins

Pins must be added after onCreate event is triggered.