Skip to content

Commit 83325fd

Browse files
Feature/on map tap callback (#292)
* Fix Clear Embedded Route * rename android package * fix linting issues partial * tap on map now gives users an event back * fixed IsSilent not being used in native * make onMapTapCallback optional from settings * fixed alternative routes on iOS --------- Co-authored-by: Emmanuel Oche <eopeter@gmail.com>
1 parent 5b46370 commit 83325fd

14 files changed

Lines changed: 147 additions & 8 deletions

File tree

android/src/main/kotlin/com/eopeter/fluttermapboxnavigation/FlutterMapboxNavigationPlugin.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class FlutterMapboxNavigationPlugin : FlutterPlugin, MethodCallHandler,
5757
var showAlternateRoutes: Boolean = true
5858
var longPressDestinationEnabled: Boolean = true
5959
var allowsUTurnsAtWayPoints: Boolean = false
60+
var enableOnMapTapCallback: Boolean = false
6061
var navigationMode = DirectionsCriteria.PROFILE_DRIVING_TRAFFIC
6162
var simulateRoute = false
6263
var enableFreeDriveMode = false
@@ -145,6 +146,11 @@ class FlutterMapboxNavigationPlugin : FlutterPlugin, MethodCallHandler,
145146
allowsUTurnsAtWayPoints = allowsUTurns
146147
}
147148

149+
val onMapTap = arguments?.get("enableOnMapTapCallback") as? Boolean
150+
if (onMapTap != null) {
151+
enableOnMapTapCallback = onMapTap
152+
}
153+
148154
val language = arguments?.get("language") as? String
149155
if (language != null) {
150156
navigationLanguage = language

android/src/main/kotlin/com/eopeter/fluttermapboxnavigation/TurnByTurn.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ open class TurnByTurn(
111111
val point = item.value as HashMap<*, *>
112112
val latitude = point["Latitude"] as Double
113113
val longitude = point["Longitude"] as Double
114-
this.addedWaypoints.add(Waypoint(Point.fromLngLat(longitude, latitude)))
114+
val isSilent = point["IsSilent"] as Boolean
115+
this.addedWaypoints.add(Waypoint(Point.fromLngLat(longitude, latitude),isSilent))
115116
}
116117
this.getRoute(this.context)
117118
result.success(true)
@@ -311,6 +312,11 @@ open class TurnByTurn(
311312
if (longPress != null) {
312313
this.longPressDestinationEnabled = longPress
313314
}
315+
316+
val onMapTap = arguments["enableOnMapTapCallback"] as? Boolean
317+
if (onMapTap != null) {
318+
this.enableOnMapTapCallback = onMapTap
319+
}
314320
}
315321

316322
open fun registerObservers() {
@@ -380,6 +386,7 @@ open class TurnByTurn(
380386
private var voiceInstructionsEnabled = true
381387
private var bannerInstructionsEnabled = true
382388
private var longPressDestinationEnabled = true
389+
private var enableOnMapTapCallback = false
383390
private var animateBuildRoute = true
384391
private var isOptimized = false
385392

android/src/main/kotlin/com/eopeter/fluttermapboxnavigation/activity/NavigationActivity.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import android.content.Intent
66
import android.content.IntentFilter
77
import android.location.Location
88
import android.os.Bundle
9+
10+
import org.json.JSONObject
911
import androidx.appcompat.app.AppCompatActivity
1012
import com.eopeter.fluttermapboxnavigation.FlutterMapboxNavigationPlugin
1113
import com.eopeter.fluttermapboxnavigation.R
@@ -24,6 +26,7 @@ import com.mapbox.geojson.Point
2426
import com.mapbox.maps.MapView
2527
import com.mapbox.maps.Style
2628
import com.mapbox.maps.plugin.gestures.OnMapLongClickListener
29+
import com.mapbox.maps.plugin.gestures.OnMapClickListener
2730
import com.mapbox.maps.plugin.gestures.gestures
2831
import com.mapbox.navigation.base.extensions.applyDefaultNavigationOptions
2932
import com.mapbox.navigation.base.extensions.applyLanguageAndVoiceUnitOptions
@@ -85,6 +88,7 @@ class NavigationActivity : AppCompatActivity() {
8588
binding = NavigationActivityBinding.inflate(layoutInflater)
8689
setContentView(binding.root)
8790
binding.navigationView.addListener(navigationStateListener)
91+
binding.navigationView.registerMapObserver(onMapClick)
8892
accessToken =
8993
PluginUtilities.getResourceFromContext(this.applicationContext, "mapbox_access_token")
9094

@@ -103,6 +107,9 @@ class NavigationActivity : AppCompatActivity() {
103107
}
104108
}
105109

110+
if (FlutterMapboxNavigationPlugin.enableOnMapTapCallback) {
111+
binding.navigationView.registerMapObserver(onMapClick)
112+
}
106113
val act = this
107114
// Add custom view binders
108115
binding.navigationView.customizeViewBinders {
@@ -182,6 +189,9 @@ class NavigationActivity : AppCompatActivity() {
182189
if (FlutterMapboxNavigationPlugin.longPressDestinationEnabled) {
183190
binding.navigationView.unregisterMapObserver(onMapLongClick)
184191
}
192+
if (FlutterMapboxNavigationPlugin.enableOnMapTapCallback) {
193+
binding.navigationView.unregisterMapObserver(onMapClick)
194+
}
185195
binding.navigationView.removeListener(navigationStateListener)
186196

187197
MapboxNavigationApp.current()?.unregisterBannerInstructionsObserver(this.bannerInstructionObserver)
@@ -426,4 +436,27 @@ class NavigationActivity : AppCompatActivity() {
426436
return false
427437
}
428438
}
439+
440+
/**
441+
* Notifies with attach and detach events on [MapView]
442+
*/
443+
private val onMapClick = object : MapViewObserver(), OnMapClickListener {
444+
445+
override fun onAttached(mapView: MapView) {
446+
mapView.gestures.addOnMapClickListener(this)
447+
}
448+
449+
override fun onDetached(mapView: MapView) {
450+
mapView.gestures.removeOnMapClickListener(this)
451+
}
452+
453+
override fun onMapClick(point: Point): Boolean {
454+
var waypoint = mapOf<String, String>(
455+
Pair("latitude", point.latitude().toString()),
456+
Pair("longitude", point.longitude().toString())
457+
)
458+
sendEvent(MapBoxEvents.ON_MAP_TAP, JSONObject(waypoint).toString())
459+
return false
460+
}
461+
}
429462
}

android/src/main/kotlin/com/eopeter/fluttermapboxnavigation/models/MapBoxEvents.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ enum class MapBoxEvents(val value: String) {
1919
ON_ARRIVAL("on_arrival"),
2020
FAILED_TO_REROUTE("failed_to_reroute"),
2121
REROUTE_ALONG("reroute_along"),
22+
ON_MAP_TAP("on_map_tap")
2223
}

android/src/main/kotlin/com/eopeter/fluttermapboxnavigation/models/views/EmbeddedNavigationMapView.kt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,18 @@ import android.content.Context
55
import android.view.View
66
import com.eopeter.fluttermapboxnavigation.TurnByTurn
77
import com.eopeter.fluttermapboxnavigation.databinding.NavigationActivityBinding
8+
import com.eopeter.fluttermapboxnavigation.models.MapBoxEvents
9+
import com.eopeter.fluttermapboxnavigation.utilities.PluginUtilities
10+
import com.mapbox.geojson.Point
11+
import com.mapbox.maps.MapView
12+
import com.mapbox.maps.plugin.gestures.OnMapClickListener
13+
import com.mapbox.maps.plugin.gestures.gestures
14+
import com.mapbox.navigation.dropin.map.MapViewObserver
815
import io.flutter.plugin.common.BinaryMessenger
916
import io.flutter.plugin.common.EventChannel
1017
import io.flutter.plugin.common.MethodChannel
1118
import io.flutter.plugin.platform.PlatformView
19+
import org.json.JSONObject
1220

1321
class EmbeddedNavigationMapView(
1422
context: Context,
@@ -38,13 +46,44 @@ class EmbeddedNavigationMapView(
3846
enableMapLongClickIntercept = false;
3947
}
4048
}
49+
50+
if((this.arguments?.get("enableOnMapTapCallback") as Boolean)) {
51+
this.binding.navigationView.registerMapObserver(onMapClick)
52+
}
4153
}
4254

4355
override fun getView(): View {
4456
return binding.root
4557
}
4658

4759
override fun dispose() {
60+
if((this.arguments?.get("enableOnMapTapCallback") as Boolean)) {
61+
this.binding.navigationView.unregisterMapObserver(onMapClick)
62+
}
4863
unregisterObservers()
4964
}
65+
66+
/**
67+
* Notifies with attach and detach events on [MapView]
68+
*/
69+
private val onMapClick = object : MapViewObserver(), OnMapClickListener {
70+
71+
override fun onAttached(mapView: MapView) {
72+
mapView.gestures.addOnMapClickListener(this)
73+
}
74+
75+
override fun onDetached(mapView: MapView) {
76+
mapView.gestures.removeOnMapClickListener(this)
77+
}
78+
79+
override fun onMapClick(point: Point): Boolean {
80+
var waypoint = mapOf<String, String>(
81+
Pair("latitude", point.latitude().toString()),
82+
Pair("longitude", point.longitude().toString())
83+
)
84+
PluginUtilities.sendEvent(MapBoxEvents.ON_MAP_TAP, JSONObject(waypoint).toString())
85+
return false
86+
}
87+
}
88+
5089
}

android/src/main/kotlin/com/eopeter/fluttermapboxnavigation/utilities/PluginUtilities.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class PluginUtilities {
4444

4545
fun sendEvent(event: MapBoxEvents, data: String = "") {
4646
val jsonString =
47-
if (MapBoxEvents.MILESTONE_EVENT == event || event == MapBoxEvents.USER_OFF_ROUTE || event == MapBoxEvents.ROUTE_BUILT) "{" +
47+
if (MapBoxEvents.MILESTONE_EVENT == event || event == MapBoxEvents.USER_OFF_ROUTE || event == MapBoxEvents.ROUTE_BUILT || event == MapBoxEvents.ON_MAP_TAP) "{" +
4848
" \"eventType\": \"${event.value}\"," +
4949
" \"data\": $data" +
5050
"}" else "{" +

ios/Classes/EmbeddedNavigationView.swift

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,13 @@ public class FlutterMapboxNavigationView : NavigationFactory, FlutterPlatformVie
145145
gesture.delegate = self
146146
navigationMapView?.addGestureRecognizer(gesture)
147147
}
148-
148+
149+
if _enableOnMapTapCallback {
150+
let onTapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
151+
onTapGesture.numberOfTapsRequired = 1
152+
onTapGesture.delegate = self
153+
navigationMapView?.addGestureRecognizer(onTapGesture)
154+
}
149155
}
150156

151157
func clearRoute(arguments: NSDictionary?, result: @escaping FlutterResult)
@@ -230,6 +236,7 @@ public class FlutterMapboxNavigationView : NavigationFactory, FlutterPlatformVie
230236

231237
routeOptions.distanceMeasurementSystem = _voiceUnits == "imperial" ? .imperial : .metric
232238
routeOptions.locale = Locale(identifier: _language)
239+
routeOptions.includesAlternativeRoutes = _alternatives
233240
self.routeOptions = routeOptions
234241

235242
// Generate the route object and draw it on the map
@@ -411,16 +418,38 @@ extension FlutterMapboxNavigationView : NavigationMapViewDelegate {
411418
}
412419

413420
extension FlutterMapboxNavigationView : UIGestureRecognizerDelegate {
414-
421+
415422
public func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
416423
return true
417424
}
418-
425+
419426
@objc func handleLongPress(_ gesture: UILongPressGestureRecognizer) {
420427
guard gesture.state == .ended else { return }
421428
let location = navigationMapView.mapView.mapboxMap.coordinate(for: gesture.location(in: navigationMapView.mapView))
422429
requestRoute(destination: location)
423430
}
431+
432+
@objc func handleTap(_ gesture: UITapGestureRecognizer) {
433+
guard gesture.state == .ended else {return}
434+
let location = navigationMapView.mapView.mapboxMap.coordinate(for: gesture.location(in: navigationMapView.mapView))
435+
let waypoint: Encodable = [
436+
"latitude" : location.latitude,
437+
"longitude" : location.longitude,
438+
]
439+
do {
440+
let encodedData = try JSONEncoder().encode(waypoint)
441+
let jsonString = String(data: encodedData,
442+
encoding: .utf8)
443+
444+
if (jsonString?.isEmpty ?? true) {
445+
return
446+
}
447+
448+
sendEvent(eventType: .on_map_tap,data: jsonString!)
449+
} catch {
450+
return
451+
}
452+
}
424453

425454
func requestRoute(destination: CLLocationCoordinate2D) {
426455
isEmbeddedNavigation = true

ios/Classes/NavigationFactory.swift

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ public class NavigationFactory : NSObject, FlutterStreamHandler
3535
var _bearing: Double = 0.0
3636
var _animateBuildRoute = true
3737
var _longPressDestinationEnabled = true
38+
var _alternatives = true
3839
var _shouldReRoute = true
3940
var _showReportFeedbackButton = true
4041
var _showEndOfRouteFeedback = true
42+
var _enableOnMapTapCallback = false
4143
var navigationDirections: Directions?
4244

4345
func addWayPoints(arguments: NSDictionary?, result: @escaping FlutterResult)
@@ -88,6 +90,8 @@ public class NavigationFactory : NSObject, FlutterStreamHandler
8890

8991
parseFlutterArguments(arguments: arguments)
9092

93+
_options?.includesAlternativeRoutes = _alternatives
94+
9195
if(_wayPoints.count > 3 && arguments?["mode"] == nil)
9296
{
9397
_navigationMode = "driving"
@@ -213,13 +217,15 @@ public class NavigationFactory : NSObject, FlutterStreamHandler
213217
_navigationMode = arguments?["mode"] as? String ?? "drivingWithTraffic"
214218
_showReportFeedbackButton = arguments?["showReportFeedbackButton"] as? Bool ?? _showReportFeedbackButton
215219
_showEndOfRouteFeedback = arguments?["showEndOfRouteFeedback"] as? Bool ?? _showEndOfRouteFeedback
220+
_enableOnMapTapCallback = arguments?["enableOnMapTapCallback"] as? Bool ?? _enableOnMapTapCallback
216221
_mapStyleUrlDay = arguments?["mapStyleUrlDay"] as? String
217222
_mapStyleUrlNight = arguments?["mapStyleUrlNight"] as? String
218223
_zoom = arguments?["zoom"] as? Double ?? _zoom
219224
_bearing = arguments?["bearing"] as? Double ?? _bearing
220225
_tilt = arguments?["tilt"] as? Double ?? _tilt
221226
_animateBuildRoute = arguments?["animateBuildRoute"] as? Bool ?? _animateBuildRoute
222227
_longPressDestinationEnabled = arguments?["longPressDestinationEnabled"] as? Bool ?? _longPressDestinationEnabled
228+
_alternatives = arguments?["alternatives"] as? Bool ?? _alternatives
223229
}
224230

225231

ios/Classes/models/EventType.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,5 @@ enum MapBoxEventType: String, Codable
1818
case on_arrival
1919
case failed_to_reroute
2020
case reroute_along
21+
case on_map_tap
2122
}

lib/src/embedded/controller.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ class MapBoxNavigationViewController {
7777
'Name': wayPoint.name,
7878
'Latitude': wayPoint.latitude,
7979
'Longitude': wayPoint.longitude,
80+
'IsSilent': wayPoint.isSilent,
8081
};
8182
pointList.add(pointMap);
8283
}

0 commit comments

Comments
 (0)