public void displayCallout(IMapAnnotation annotation, IAnnotationMarker annotationElement) { // Hide any existing callout hideCallout(); // There is only ever one callout MapCallout callout = new MapCallout(); calloutLayer.Children.Add(callout); // Hook up tap event callout.Callout_Tapped += callout_Callout_Tapped; // Assign this annotation as the data context of the callout - so it can get Title, Subtitle, etc callout.DataContext = annotation; // Position MapLayer.SetPosition(callout, new Location(annotation.Latitude, annotation.Longitude)); // Callout anchor point also depends upon the anchor of the pushpin MapLayer.SetPositionAnchor(callout, new Windows.Foundation.Point( CALLOUT_ANCHOR_X + annotationElement.PositionAnchor.X, CALLOUT_ANCHOR_Y + annotationElement.PositionAnchor.Y)); // Appear callout.animateOnscreen(); Point offsetRequired; if (!isCalloutInView(callout, out offsetRequired)) map.scrollBy(offsetRequired); // Store for later lastCallout = callout; }
// Helpers bool isCalloutInView(MapCallout callout, out Point offsetRequired) { offsetRequired = new Point(); Location calloutLocation = MapLayer.GetPosition(callout); Point calloutTranslation = MapLayer.GetPositionAnchor(callout); Point calloutPixelLocation; if (!map.TryLocationToPixel(calloutLocation, out calloutPixelLocation)) throw new Exception("Cannot get location of callout "); // Where is the callout? Point calloutTopLeftLocation = new Point(calloutPixelLocation.X - calloutTranslation.X, calloutPixelLocation.Y - calloutTranslation.Y); Rect calloutRect = new Rect(calloutTopLeftLocation, new Size(MapConstants.CalloutWidth, MapConstants.CalloutHeight)); // Work out if it is within the map boundary double offsetXRequired = 0; double offsetYRequired = 0; double mapWidth = map.ActualWidth; double mapHeight = map.ActualHeight; if (calloutRect.Left < 0) offsetXRequired = (0 - calloutRect.Left); else if (calloutRect.Right > mapWidth) offsetXRequired = (mapWidth - calloutRect.Right); if (calloutRect.Top < 0) offsetYRequired = (0 - calloutRect.Top); else if (calloutRect.Bottom > mapHeight) offsetYRequired = (mapHeight - calloutRect.Bottom); offsetRequired = new Point(offsetXRequired, offsetYRequired); return (offsetXRequired == 0) && (offsetYRequired == 0); }
public void hideCallout() { if (lastCallout == null) return; // Unhook tapped event lastCallout.Callout_Tapped -= callout_Callout_Tapped; // Animate disappearance lastCallout.Callout_Disappeared += lastCallout_Callout_Disappeared; lastCallout.animateOffscreen(); lastCallout = null; }