Nutiteq is now part of CARTO! Please use latest CARTO Mobile SDK for new projects. Nutiteq SDK 3.x support and updates ended in 2017, documentation here is outdated.
Listen events for map touches
Introduction
Once you have implemented and set MapEventListener interface for MapView, this will get following events, with following data as their parameter value:
- onMapMoved - map moving, zooming, tilting, rotating. Note that this is called for each pixel movement, so any work in this method can make map panning animation visibly slower.
- onMapClicked(MapClickInfo) - map clicked, provides info about click:
- ClickType - gives
CLICK_TYPE_SINGLE
,CLICK_TYPE_LONG
,CLICK_TYPE_DOUBLE
orCLICK_TYPE_DUAL
- ClickPos - geographical click position (in map projection)
- ClickType - gives
- onVectorElementClicked(VectorElementsClickInfo) - any vector object on map was clicked (could be line,polygon,point,marker,balloon popup or a 3D model)
- ClickType - see above
- VectorElementClickInfos - sorted list of clicked objects, nearest is first. Each ClickInfo has:
- ClickPos - geographical click location
- ElementClickPos - click locaton projected to element, different from ClickPos if click was not precisely on object (hint: it never really is).
- Distance - distance from the vector element to the camera
- Order - order of element within VectorElementClickInfos
- VectorElement - actual clicked element
1. Implement MapEventListener
Create new class called MyMapEventListener which implements MapEventListner interface.
// MyMapEventListener.h: #import <Nuti/Nuti.h> @interface MyMapEventListener : NTMapEventListener -(void)onMapMoved; -(void)onMapClicked:(NTMapClickInfo*)mapClickInfo; -(void)onVectorElementClicked:(NTVectorElementsClickInfo*)vectorElementsClickInfo; @end // MyMapEventListener.mm: #import "MyMapEventListener.h" @interface MyMapEventListener() { } @end; @implementation MyMapEventListener -(void)onMapMoved { // called very often, even just console logging can lag map movement animation // NSLog(@"Map moved!"); } -(void)onMapClicked:(NTMapClickInfo*)mapClickInfo { // Check the type of the click NSString* clickMsg; if ([mapClickInfo getClickType] == NT_CLICK_TYPE_SINGLE) { clickMsg = @"Single map click!"; } else if ([mapClickInfo getClickType] == NT_CLICK_TYPE_LONG) { clickMsg = @"Long map click!"; } else if ([mapClickInfo getClickType] == NT_CLICK_TYPE_DOUBLE) { clickMsg = @"Double map click!"; } else if ([mapClickInfo getClickType] == NT_CLICK_TYPE_DUAL) { clickMsg = @"Dual map click!"; } NTMapPos* clickPos = [mapClickInfo getClickPos]; NTMapPos* wgs84Clickpos = [[[_mapView getOptions] getBaseProjection] toWgs84:clickPos]; NSLog(@"%@ Location: %@", clickMsg, [NSString stringWithFormat:@"%f, %f", [wgs84Clickpos getY], [wgs84Clickpos getX]]); } -(void)onVectorElementClicked:(NTVectorElementsClickInfo*)vectorElementsClickInfo { NSLog(@"Vector element click!"); // Multiple vector elements can be clicked at the same time, we only care about the one // closest to the camera NTVectorElementClickInfo* clickInfo = [[vectorElementsClickInfo getVectorElementClickInfos] get:0]; // Load metadata from the object NTVectorElement* vectorElement = [clickInfo getVectorElement]; NSString* clickText = [vectorElement getMetaDataElement:@"ClickText"]; if (clickText == nil || [clickText length] == 0) { return; } NSLog(@"Vector element clicked, metadata : '%@'", clickText); } @end
// MyMapEventListener.java : // imports omitted... /** * A custom map event listener that displays information about map events and creates pop-ups. */ public class MyMapEventListener extends MapEventListener { private MapView mapView; private LocalVectorDataSource vectorDataSource; private BalloonPopup oldClickLabel; public MyMapEventListener(MapView mapView, LocalVectorDataSource vectorDataSource) { this.mapView = mapView; this.vectorDataSource = vectorDataSource; } @Override public void onMapMoved() { final MapPos topLeft = mapView.screenToMap(new ScreenPos(0, 0)); final MapPos bottomRight = mapView.screenToMap(new ScreenPos(mapView.getWidth(), mapView.getHeight())); Log.d(Const.LOG_TAG, mapView.getOptions().getBaseProjection().toWgs84(topLeft) + " " + mapView.getOptions().getBaseProjection().toWgs84(bottomRight)); } @Override public void onMapClicked(MapClickInfo mapClickInfo) { Log.d(Const.LOG_TAG, "Map click!"); // Remove old click label if (oldClickLabel != null) { vectorDataSource.remove(oldClickLabel); oldClickLabel = null; } BalloonPopupStyleBuilder styleBuilder = new BalloonPopupStyleBuilder(); // Make sure this label is shown on top all other labels styleBuilder.setPlacementPriority(10); // Check the type of the click String clickMsg = null; if (mapClickInfo.getClickType() == ClickType.CLICK_TYPE_SINGLE) { clickMsg = "Single map click!"; } else if (mapClickInfo.getClickType() == ClickType.CLICK_TYPE_LONG) { clickMsg = "Long map click!"; } else if (mapClickInfo.getClickType() == ClickType.CLICK_TYPE_DOUBLE) { clickMsg = "Double map click!"; } else if (mapClickInfo.getClickType() == ClickType.CLICK_TYPE_DUAL) { clickMsg ="Dual map click!"; } MapPos clickPos = mapClickInfo.getClickPos(); MapPos wgs84Clickpos = mapView.getOptions().getBaseProjection().toWgs84(clickPos); String msg = String.format(Locale.US, "%.4f, %.4f", wgs84Clickpos.getY(), wgs84Clickpos.getX()); BalloonPopup clickPopup = new BalloonPopup(mapClickInfo.getClickPos(), styleBuilder.buildStyle(), clickMsg, msg); vectorDataSource.add(clickPopup); oldClickLabel = clickPopup; } @Override public void onVectorElementClicked(VectorElementsClickInfo vectorElementsClickInfo) { Log.d(Const.LOG_TAG, "Vector element click!"); // Remove old click label if (oldClickLabel != null) { vectorDataSource.remove(oldClickLabel); oldClickLabel = null; } // Multiple vector elements can be clicked at the same time, we only care about the one // closest to the camera VectorElementClickInfo clickInfo = vectorElementsClickInfo.getVectorElementClickInfos().get(0); // Check the type of vector element BalloonPopup clickPopup = null; BalloonPopupStyleBuilder styleBuilder = new BalloonPopupStyleBuilder(); // Configure style styleBuilder.setLeftMargins(new BalloonPopupMargins(0, 0, 0, 0)); styleBuilder.setTitleMargins(new BalloonPopupMargins(6, 3, 6, 3)); // Make sure this label is shown on top all other labels styleBuilder.setPlacementPriority(10); VectorElement vectorElement = clickInfo.getVectorElement(); String clickText = vectorElement.getMetaDataElement("ClickText"); if (clickText == null || clickText.length() == 0) { return; } if (vectorElement instanceof Billboard) { // If the element is billboard, attach the click label to the billboard element Billboard billboard = (Billboard) vectorElement; clickPopup = new BalloonPopup(billboard, styleBuilder.buildStyle(), clickText, ""); } else { // for lines and polygons set label to click location clickPopup = new BalloonPopup(clickInfo.getElementClickPos(), styleBuilder.buildStyle(), clickText, ""); } vectorDataSource.add(clickPopup); oldClickLabel = clickPopup; } }
// MapListener.cs : // using statements skipped namespace HelloMap { public class MapListener : MapEventListener { private LocalVectorDataSource _dataSource; private BalloonPopup _oldClickLabel; public MapListener(LocalVectorDataSource dataSource) { _dataSource = dataSource; } public override void OnMapClicked (MapClickInfo mapClickInfo) { // Remove old click label if (_oldClickLabel != null) { _dataSource.Remove(_oldClickLabel); _oldClickLabel = null; } } public override void OnMapMoved() { } public override void OnVectorElementClicked(VectorElementsClickInfo vectorElementsClickInfo) { // A note about iOS: DISABLE 'Optimize PNG files for iOS' option in iOS build settings, // otherwise icons can not be loaded using AssetUtils/Bitmap constructor as Xamarin converts // PNGs to unsupported custom format. // Remove old click label if (_oldClickLabel != null) { _dataSource.Remove(_oldClickLabel); _oldClickLabel = null; } var clickInfo = vectorElementsClickInfo.VectorElementClickInfos[0]; var styleBuilder = new BalloonPopupStyleBuilder(); // Configure simple style styleBuilder.LeftMargins = new BalloonPopupMargins (0, 3, 0, 6); styleBuilder.RightMargins = new BalloonPopupMargins (0, 3, 0, 6); // Make sure this label is shown on top all other labels styleBuilder.PlacementPriority = 10; var vectorElement = clickInfo.VectorElement; var clickText = vectorElement.GetMetaDataElement("ClickText"); var clickPopup = new BalloonPopup(clickInfo.ElementClickPos, styleBuilder.BuildStyle(), clickText, ""); _dataSource.Add(clickPopup); _oldClickLabel = clickPopup; } } }
2. Initialize listener
// 1. Create a map event listener MyMapEventListener* mapListener = [[MyMapEventListener alloc] init]; [self setMapEventListener:mapListener];
mapView.setMapEventListener(new MyMapEventListener(mapView, vectorDataSource));
// Create and set map listener mapView.MapEventListener = new MapListener (dataSource);