new Button {
Text = "Add pins",
Command = new Command (() => {
-
foreach (var pin in map.Pins) {
+#pragma warning disable CS0618
pin.Clicked -= PinClicked;
+#pragma warning restore CS0618
}
map.Pins.Clear ();
Type = PinType.Place,
Position = new Position (map.VisibleRegion.Center.Latitude + lat, map.VisibleRegion.Center.Longitude + lng)
};
-
+#pragma warning disable CS0618
pin.Clicked += PinClicked;
+#pragma warning restore CS0618
map.Pins.Add (pin);
}
})
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
Placeholder="Search Address"
SearchButtonPressed="SearchForAddress" />
- <Label x:Name="LastPinClickLabel"
- Grid.Row="2" />
- <Label x:Name="LastMapClickLabel"
- Grid.Row="3" />
- <ScrollView Grid.Row="4">
+ <Label
+ x:Name="LastMarkerClickLabel"
+ Grid.Row="2" />
+ <Label
+ x:Name="LastInfoWindowClickLabel"
+ Grid.Row="3" />
+ <Label
+ x:Name="LastMapClickLabel"
+ Grid.Row="4" />
+ <ScrollView Grid.Row="5">
<StackLayout>
<Button Clicked="MapTypeClicked"
Text="Map Type" />
InitializeComponent();
Map = MakeMap();
- Map.Pins.ForEach(pin => pin.Clicked += PinClicked);
+ Map.Pins.ForEach(pin =>
+ {
+ pin.MarkerClicked += MarkerClicked;
+ pin.InfoWindowClicked += InfoWindowClicked;
+ });
Map.MapClicked += MapClicked;
((Grid)Content).Children.Add(Map, 0, 1);
};
}
- void PinClicked(object sender, EventArgs e)
+ void MarkerClicked(object sender, PinClickedEventArgs e)
+ {
+ LastMarkerClickLabel.Text = $"Last Marker Clicked: {((Pin)sender).Label}";
+ }
+
+ void InfoWindowClicked(object sender, PinClickedEventArgs e)
{
- LastPinClickLabel.Text = $"Last Pin Clicked: {((Pin)sender).Label}";
+ LastInfoWindowClickLabel.Text = $"Last Info Window Clicked: {((Pin)sender).Label}";
+ e.HideInfoWindow = true;
}
async void SearchForAddress(object sender, EventArgs e)
{
NativeMap.MyLocationEnabled = false;
NativeMap.SetOnCameraMoveListener(null);
- NativeMap.InfoWindowClick -= MapOnMarkerClick;
+ NativeMap.MarkerClick -= OnMarkerClick;
+ NativeMap.InfoWindowClick -= OnInfoWindowClick;
NativeMap.MapClick -= OnMapClick;
NativeMap.Dispose();
NativeMap = null;
if (NativeMap != null)
{
NativeMap.SetOnCameraMoveListener(null);
- NativeMap.InfoWindowClick -= MapOnMarkerClick;
+ NativeMap.MarkerClick -= OnMarkerClick;
+ NativeMap.InfoWindowClick -= OnInfoWindowClick;
NativeMap.MapClick -= OnMapClick;
NativeMap = null;
}
}
map.SetOnCameraMoveListener(this);
- map.InfoWindowClick += MapOnMarkerClick;
+ map.MarkerClick += OnMarkerClick;
+ map.InfoWindowClick += OnInfoWindowClick;
map.MapClick += OnMapClick;
map.UiSettings.ZoomControlsEnabled = Map.HasZoomEnabled;
return _markers?.Find(m => m.Id == (string)pin.MarkerId);
}
- void MapOnMarkerClick(object sender, GoogleMap.InfoWindowClickEventArgs eventArgs)
+ protected Pin GetPinForMarker(Marker marker)
{
- // clicked marker
- var marker = eventArgs.Marker;
-
- // lookup pin
Pin targetPin = null;
- for (var i = 0; i < Map.Pins.Count; i++)
+
+ for (int i = 0; i < Map.Pins.Count; i++)
{
- Pin pin = Map.Pins[i];
- if ((string)pin.MarkerId != marker.Id)
+ var pin = Map.Pins[i];
+ if ((string)pin.MarkerId == marker.Id)
{
- continue;
+ targetPin = pin;
+ break;
}
+ }
+
+ return targetPin;
+ }
+
+ void OnMarkerClick(object sender, GoogleMap.MarkerClickEventArgs e)
+ {
+ var pin = GetPinForMarker(e.Marker);
+
+ if (pin == null)
+ {
+ return;
+ }
+
+ // Setting e.Handled = true will prevent the info window from being presented
+ // SendMarkerClick() returns the value of PinClickedEventArgs.HideInfoWindow
+ bool handled = pin.SendMarkerClick();
+ e.Handled = handled;
+ }
+
+ void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
+ {
+ var marker = e.Marker;
+ var pin = GetPinForMarker(marker);
- targetPin = pin;
- break;
+ if (pin == null)
+ {
+ return;
}
- // only consider event handled if a handler is present.
- // Else allow default behavior of displaying an info window.
- targetPin?.SendTap();
+#pragma warning disable CS0618
+ pin.SendTap();
+#pragma warning restore CS0618
+
+ // SendInfoWindowClick() returns the value of PinClickedEventArgs.HideInfoWindow
+ bool hideInfoWindow = pin.SendInfoWindowClick();
+ if (hideInfoWindow)
+ {
+ marker.HideInfoWindow();
+ }
}
void OnMapClick(object sender, GoogleMap.MapClickEventArgs e)
if(pin.Position.Latitude == marker.Position.Lat &&
pin.Position.Longitude == marker.Position.Lng)
{
- pin.SendTap();
- break;
+#pragma warning disable CS0618
+ pin.SendTap();
+#pragma warning restore CS0618
+ break;
}
}
}
pin.MarkerId = nativePin;
nativePin.Clicked += (s, e) =>
{
+#pragma warning disable CS0618
pin.SendTap();
+#pragma warning restore CS0618
};
Control.Add(nativePin);
_pins.Add(pin);
void PushPinTapped(object sender, TappedRoutedEventArgs e)
{
+#pragma warning disable CS0618
_pin.SendTap();
+#pragma warning restore CS0618
+ _pin.SendMarkerClick();
}
void UpdateLocation()
void FormsPushPin_MouseDown(object sender, MouseButtonEventArgs e)
{
+#pragma warning disable CS0618
Pin.SendTap();
+#pragma warning restore CS0618
}
void PinPropertyChanged(object sender, PropertyChangedEventArgs e)
-using System;
-using System.Collections;
-using System.Collections.Generic;
+using System.Collections;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using MapKit;
using ObjCRuntime;
using RectangleF = CoreGraphics.CGRect;
-using Foundation;
#if __MOBILE__
using UIKit;
}
var mkMapView = (MKMapView)Control;
+ mkMapView.DidSelectAnnotationView -= MkMapViewOnAnnotationViewSelected;
mkMapView.RegionChanged -= MkMapViewOnRegionChanged;
mkMapView.GetViewForAnnotation = null;
if (mkMapView.Delegate != null)
SetNativeControl(mapView);
mapView.GetViewForAnnotation = GetViewForAnnotation;
+ mapView.DidSelectAnnotationView += MkMapViewOnAnnotationViewSelected;
mapView.RegionChanged += MkMapViewOnRegionChanged;
#if __MOBILE__
mapView.AddGestureRecognizer(_mapClickedGestureRecognizer = new UITapGestureRecognizer(OnMapClicked));
}
#if __MOBILE__
- var recognizer = new UITapGestureRecognizer(g => OnClick(annotation, g))
+ var recognizer = new UITapGestureRecognizer(g => OnCalloutClicked(annotation))
{
ShouldReceiveTouch = (gestureRecognizer, touch) =>
{
}
};
#else
- var recognizer = new NSClickGestureRecognizer(g => OnClick(annotation, g));
+ var recognizer = new NSClickGestureRecognizer(g => OnCalloutClicked(annotation));
#endif
mapPin.AddGestureRecognizer(recognizer);
}
-#if __MOBILE__
- void OnClick(object annotationObject, UITapGestureRecognizer recognizer)
-#else
- void OnClick(object annotationObject, NSClickGestureRecognizer recognizer)
-#endif
+ protected Pin GetPinForAnnotation(IMKAnnotation annotation)
{
- // https://bugzilla.xamarin.com/show_bug.cgi?id=26416
- NSObject annotation = Runtime.GetNSObject(((IMKAnnotation)annotationObject).Handle);
- if (annotation == null)
- return;
-
- // lookup pin
Pin targetPin = null;
- foreach (Pin pin in ((Map)Element).Pins)
+ var map = (Map)Element;
+
+ for (int i = 0; i < map.Pins.Count; i++)
{
- object target = pin.MarkerId;
- if (target != annotation)
- continue;
+ var pin = map.Pins[i];
+ if ((IMKAnnotation)pin.MarkerId == annotation)
+ {
+ targetPin = pin;
+ break;
+ }
+ }
- targetPin = pin;
- break;
+ return targetPin;
+ }
+
+ void MkMapViewOnAnnotationViewSelected(object sender, MKAnnotationViewEventArgs e)
+ {
+ var annotation = e.View.Annotation;
+ var pin = GetPinForAnnotation(annotation);
+
+ if (pin != null)
+ {
+ // SendMarkerClick() returns the value of PinClickedEventArgs.HideInfoWindow
+ // Hide the info window by deselecting the annotation
+ bool deselect = pin.SendMarkerClick();
+ if (deselect)
+ {
+ ((MKMapView)Control).DeselectAnnotation(annotation, false);
+ }
}
+ }
+
+ void OnCalloutClicked(IMKAnnotation annotation)
+ {
+ // lookup pin
+ Pin targetPin = GetPinForAnnotation(annotation);
// pin not found. Must have been activated outside of forms
if (targetPin == null)
if (_lastTouchedView is MKAnnotationView)
return;
+#pragma warning disable CS0618
targetPin.SendTap();
+#pragma warning restore CS0618
+
+ // SendInfoWindowClick() returns the value of PinClickedEventArgs.HideInfoWindow
+ // Hide the info window by deselecting the annotation
+ bool deselect = targetPin.SendInfoWindowClick();
+ if (deselect)
+ {
+ ((MKMapView)Control).DeselectAnnotation(annotation, true);
+ }
}
#if __MOBILE__
}
}
+ [Obsolete("This event is obsolete as of 4.3.0. Please use MarkerClicked and/or InfoWindowClicked instead.")]
public event EventHandler Clicked;
+ public event EventHandler<PinClickedEventArgs> MarkerClicked;
+
+ public event EventHandler<PinClickedEventArgs> InfoWindowClicked;
+
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj))
}
[EditorBrowsable(EditorBrowsableState.Never)]
+ [Obsolete("This method is obsolete as of 4.3.0.")]
public bool SendTap()
{
EventHandler handler = Clicked;
return true;
}
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool SendMarkerClick()
+ {
+ var args = new PinClickedEventArgs();
+ MarkerClicked?.Invoke(this, args);
+ return args.HideInfoWindow;
+ }
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public bool SendInfoWindowClick()
+ {
+ var args = new PinClickedEventArgs();
+ InfoWindowClicked?.Invoke(this, args);
+ return args.HideInfoWindow;
+ }
+
bool Equals(Pin other)
{
return string.Equals(Label, other.Label) && Equals(Position, other.Position) && Type == other.Type && string.Equals(Address, other.Address);
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Xamarin.Forms.Maps
+{
+ public class PinClickedEventArgs : EventArgs
+ {
+ public bool HideInfoWindow { get; set; }
+
+ public PinClickedEventArgs()
+ {
+ HideInfoWindow = false;
+ }
+ }
+}