|
This example demonstrates how to render a compass icon that displays the heading rotation of an interactive map. The compass indicates the direction where 0 degrees is north, 90 degrees is east, 180 degrees is south, and 270 degrees is west. You will also learn how to rotate the map back to its default north-up orientation.
Initial map rotation angle, north pointing up
Map rotation angle changed, north pointing differently
UI and Map Integration
The MainActivity
overrides the onCreate()
function which defines the buttonAsStart
/ buttonAsStop
methods used to turn the compass on or off, as well as color the button green
/ red
, respectively, and a listener for that button, btnEnableLiveHeading.setOnClickListener
.
The button listener calls startLiveHeading()
or stopLiveHeading()
to start or stop reading the live compass sensor data from the device, by adding or removing a listener to the compass data source.
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
increment()
surfaceView = findViewById(R.id.gem_surface)
compass = findViewById(R.id.compass)
btnEnableLiveHeading = findViewById(R.id.btn_enable_live_heading)
statusText = findViewById(R.id.status_text)
buttonAsStart(this, btnEnableLiveHeading)
btnEnableLiveHeading.setOnClickListener {
isLiveHeadingEnabled.set(!isLiveHeadingEnabled.get())
if (isLiveHeadingEnabled.get())
{
buttonAsStop(this, btnEnableLiveHeading)
statusText.text = getString(R.string.live_heading_enabled)
}
else
{
buttonAsStart(this, btnEnableLiveHeading)
statusText.text = getString(R.string.live_heading_disabled)
}
GemCall.execute {
if (isLiveHeadingEnabled.get())
{
startLiveHeading()
}
else
{
stopLiveHeading()
}
}
}
}
The compass data source listener, when active, reads the compass sensor, smoothed into an average of several readings, and passes this heading to the mapView
to rotate the map accordingly, when the device is rotated.
private var dataSourceListener = object : DataSourceListener()
{
override fun onNewData(data: SenseData)
{
GemCall.execute {
val heading = headingSmoother.update(CompassData(data).heading)
surfaceView.mapView?.preferences?.rotationAngle = heading
}
}
}
Compass Functionality
This code sets up a callback onMapDataReady
that executes when map data is ready. If the data isn't ready, it exits.
Otherwise, it makes the compass visible and then it links the compass UI:
- The compass image rotates as the map view rotates
- Tapping the compass icon makes the map smoothly animate to a north-up orientation.
SdkSettings.onMapDataReady = onMapDataReady@{ isReady ->
if (!isReady) return@onMapDataReady
if(!mainActivityIdlingResource.isIdleNow)
decrement()
compass.visibility = View.VISIBLE
btnEnableLiveHeading.visibility = View.VISIBLE
statusText.visibility = View.VISIBLE
surfaceView.mapView?.let { mapView ->
mapView.onMapAngleUpdated = {
compass.rotation = -it.toFloat()
}
compass.setOnClickListener {
GemCall.execute {
mapView.alignNorthUp(Animation(EAnimation.Linear, 300))
}
}
}
}
The red stop button removes the compass sensor data source listener, thus the heading is no longer updated and the map stops rotating when the device is rotated.
private fun stopLiveHeading() = GemCall.execute {
dataSource?.release()
dataSource = null
}