+++ /dev/null
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using Xamarin.Forms.Maps;
-
-namespace Xamarin.Forms.Controls
-{
- public class MapGallery : ContentPage
- {
- readonly StackLayout _stack;
-
- public MapGallery ()
- {
- if (Device.RuntimePlatform == Device.iOS && Device.Idiom == TargetIdiom.Tablet)
- Padding = new Thickness(0, 0, 0, 60);
-
- var map = MakeMap ();
-
- map.MoveToRegion (MapSpan.FromCenterAndRadius (new Position (41.890202, 12.492049), Distance.FromMiles (0.5)));
-
- var searchAddress = new SearchBar { Placeholder = "Search Address" };
-
- searchAddress.SearchButtonPressed += async (e, a) => {
- var addressQuery = searchAddress.Text;
- searchAddress.Text = "";
- searchAddress.Unfocus ();
-
- var positions = (await (new Geocoder ()).GetPositionsForAddressAsync (addressQuery)).ToList ();
- if (!positions.Any ())
- return;
-
- var position = positions.First ();
- map.MoveToRegion (MapSpan.FromCenterAndRadius (position,
- Distance.FromMeters (4000)));
- map.Pins.Add (new Pin {
- Label = addressQuery,
- Position = position,
- Address = addressQuery
- });
- };
-
- var buttonAddressFromPosition = new Button { Text = "Address From Position" };
- buttonAddressFromPosition.Clicked += async (e, a) => {
- var addresses = (await (new Geocoder ()).GetAddressesForPositionAsync (new Position (41.8902, 12.4923))).ToList ();
- foreach (var ad in addresses)
- Debug.WriteLine (ad);
- };
-
- var buttonZoomIn = new Button { Text = "Zoom In" };
- buttonZoomIn.Clicked += (e, a) => map.MoveToRegion (map.VisibleRegion.WithZoom (5f));
-
- var buttonZoomOut = new Button { Text = "Zoom Out" };
- buttonZoomOut.Clicked += (e, a) => map.MoveToRegion (map.VisibleRegion.WithZoom (1 / 3f));
-
- var mapTypeButton = new Button { Text = "Map Type" };
- mapTypeButton.Clicked += async (e, a) => {
- var result = await DisplayActionSheet ("Select Map Type", null, null, "Street", "Satellite", "Hybrid");
- switch (result) {
- case "Street":
- map.MapType = MapType.Street;
- break;
- case "Satellite":
- map.MapType = MapType.Satellite;
- break;
- case "Hybrid":
- map.MapType = MapType.Hybrid;
- break;
- }
- };
-
- var buttonHome = new Button { Text = "Home" };
- buttonHome.Clicked += (a, e) => {
- map.MoveToRegion (MapSpan.FromCenterAndRadius (new Position (41.890202, 12.492049), Distance.FromMiles (0.5)));
- };
-
- var buttonRemove = new Button { Text = "Remove Pin" };
- buttonRemove.Clicked += (a, e) =>
- {
- map.Pins.RemoveAt(0);
- };
-
- _stack = new StackLayout {
- Spacing = 0,
- Padding = new Thickness (30, 0)
- };
- //stack.SetRowSpacing (1, 0);
-
- Title = "Map Gallery";
-
- var buttonZoomPin = new Button { Text = "Zoom Pin" };
- buttonZoomPin.Clicked += (a, e) => {
- var pos = new Position (41.011995, -8.642995);
- map.Pins.Clear ();
- map.Pins.Add (new Pin { Position = pos, Label = "Rui" });
- map.MoveToRegion (MapSpan.FromCenterAndRadius (pos, Distance.FromMiles (0.5)));
- };
-
- var buttonEditPin = new Button { Text = "Edit Pin" };
- buttonEditPin.Clicked += (a, e) =>
- {
- var pin = map.Pins.First();
-
- pin.Label += " Edited";
- pin.Address = "Edited";
-
- var pos = new Position(pin.Position.Latitude + 1, pin.Position.Longitude + 1);
- pin.Position = pos;
- map.MoveToRegion(MapSpan.FromCenterAndRadius(pos, Distance.FromMiles(0.5)));
- };
-
- map.VerticalOptions = LayoutOptions.FillAndExpand;
- _stack.Children.Add (searchAddress);
- _stack.Children.Add (map);
- _stack.Children.Add (mapTypeButton);
- _stack.Children.Add (buttonZoomIn);
- _stack.Children.Add (buttonZoomOut);
- _stack.Children.Add (buttonAddressFromPosition);
- _stack.Children.Add (buttonHome);
- _stack.Children.Add (buttonZoomPin);
- _stack.Children.Add (buttonEditPin);
- _stack.Children.Add (buttonRemove);
-
- Content = _stack;
- }
-
- public static Map MakeMap ()
- {
- Pin colosseum = null;
- Pin pantheon = null;
- Pin chapel = null;
-
- var map = new Map {
- IsShowingUser = false,
- Pins = {
- (colosseum = new Pin {
- Type = PinType.Place,
- Position = new Position (41.890202, 12.492049),
- Label = "Colosseum",
- Address = "Piazza del Colosseo, 00184 Rome, Province of Rome, Italy"
- }),
- (pantheon = new Pin {
- Type = PinType.Place,
- Position = new Position (41.898652, 12.476831),
- Label = "Pantheon",
- Address = "Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"
- }),
- (chapel = new Pin {
- Type = PinType.Place,
- Position = new Position (41.903209, 12.454545),
- Label = "Sistine Chapel",
- Address = "Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"
- })
- }
- };
-
- colosseum.Clicked += PinClicked;
- pantheon.Clicked += PinClicked;
- chapel.Clicked += PinClicked;
- return map;
- }
-
- static void PinClicked (object sender, EventArgs e)
- {
- Pin pin = (Pin)sender;
- Application.Current.MainPage.DisplayAlert("Pin Click",
- $"You clicked the {pin.Label} pin, located at {pin.Address}, or coordinates ({pin.Position.Latitude}, {pin.Position.Longitude})",
- "OK");
- }
- }
-}
--- /dev/null
+<?xml version="1.0" encoding="utf-8" ?>
+<ContentPage
+ x:Class="Xamarin.Forms.Controls.MapGallery"
+ xmlns="http://xamarin.com/schemas/2014/forms"
+ xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
+ xmlns:maps="clr-namespace:Xamarin.Forms.Maps;assembly=Xamarin.Forms.Maps"
+ Title="Map Gallery">
+ <Grid>
+ <Grid.RowDefinitions>
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="Auto" />
+ <RowDefinition Height="*" />
+ </Grid.RowDefinitions>
+
+ <SearchBar
+ Grid.Row="0"
+ Placeholder="Search Address"
+ SearchButtonPressed="SearchForAddress" />
+
+ <Label
+ x:Name="LastPinClickLabel"
+ Grid.Row="2" />
+ <Label
+ x:Name="LastMapClickLabel"
+ Grid.Row="3" />
+ <ScrollView Grid.Row="4">
+ <StackLayout>
+ <Button
+ Clicked="MapTypeClicked"
+ Text="Map Type" />
+ <Button
+ Clicked="ZoomInClicked"
+ Text="Zoom In" />
+ <Button
+ Clicked="ZoomOutClicked"
+ Text="Zoom Out" />
+ <Button
+ Clicked="ReverseGeocodeClicked"
+ Text="Address From Position" />
+ <Button
+ Clicked="HomeClicked"
+ Text="Home" />
+ <Button
+ Clicked="ZoomPinClicked"
+ Text="Zoom Pin" />
+ <Button
+ Clicked="EditPinClicked"
+ Text="Edit Pin" />
+ <Button
+ Clicked="RemovePinClicked"
+ Text="Remove Pin" />
+ </StackLayout>
+ </ScrollView>
+ </Grid>
+</ContentPage>
\ No newline at end of file
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+using Xamarin.Forms;
+using Xamarin.Forms.Internals;
+using Xamarin.Forms.Maps;
+using Xamarin.Forms.Xaml;
+
+namespace Xamarin.Forms.Controls
+{
+ [XamlCompilation(XamlCompilationOptions.Compile)]
+ public partial class MapGallery : ContentPage
+ {
+ readonly Geocoder _geocoder = new Geocoder();
+ readonly Map Map;
+
+ public MapGallery()
+ {
+ InitializeComponent();
+
+ Map = MakeMap();
+ Map.Pins.ForEach(pin => pin.Clicked += PinClicked);
+ Map.MapClicked += MapClicked;
+
+ ((Grid)Content).Children.Add(Map, 0, 1);
+ }
+
+ public static Map MakeMap()
+ {
+ return new Map(MapSpan.FromCenterAndRadius(new Position(41.890202, 12.492049), Distance.FromMiles(0.5)))
+ {
+ IsShowingUser = false,
+ Pins =
+ {
+ new Pin
+ {
+ Type = PinType.Place,
+ Position = new Position (41.890202, 12.492049),
+ Label = "Colosseum",
+ Address = "Piazza del Colosseo, 00184 Rome, Province of Rome, Italy"
+ },
+ new Pin
+ {
+ Type = PinType.Place,
+ Position = new Position (41.898652, 12.476831),
+ Label = "Pantheon",
+ Address = "Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"
+ },
+ new Pin
+ {
+ Type = PinType.Place,
+ Position = new Position (41.903209, 12.454545),
+ Label = "Sistine Chapel",
+ Address = "Piazza della Rotunda, 00186 Rome, Province of Rome, Italy"
+ }
+ }
+ };
+ }
+
+ void PinClicked(object sender, EventArgs e)
+ {
+ LastPinClickLabel.Text = $"Last Pin Clicked: {((Pin)sender).Label}";
+ }
+
+ async void SearchForAddress(object sender, EventArgs e)
+ {
+ var searchAddress = (SearchBar)sender;
+ var addressQuery = searchAddress.Text;
+ searchAddress.Text = "";
+ searchAddress.Unfocus();
+
+ var positions = (await _geocoder.GetPositionsForAddressAsync(addressQuery)).ToList();
+ if (!positions.Any())
+ return;
+
+ var position = positions.First();
+ Map.MoveToRegion(MapSpan.FromCenterAndRadius(position, Distance.FromMeters(4000)));
+ Map.Pins.Add(new Pin
+ {
+ Label = addressQuery,
+ Position = position,
+ Address = addressQuery
+ });
+ }
+
+ void MapClicked(object sender, MapClickedEventArgs e)
+ {
+ LastMapClickLabel.Text = $"Last MapClick: {e.Position.Latitude}, {e.Position.Longitude}";
+ }
+
+ async void MapTypeClicked(object sender, EventArgs e)
+ {
+ var result = await DisplayActionSheet("Select Map Type", null, null, "Street", "Satellite", "Hybrid");
+ switch (result)
+ {
+ case "Street":
+ Map.MapType = MapType.Street;
+ break;
+ case "Satellite":
+ Map.MapType = MapType.Satellite;
+ break;
+ case "Hybrid":
+ Map.MapType = MapType.Hybrid;
+ break;
+ }
+ }
+
+ void ZoomInClicked(object sender, EventArgs e)
+ {
+ Map.MoveToRegion(Map.VisibleRegion.WithZoom(5f));
+ }
+
+ void ZoomOutClicked(object sender, EventArgs e)
+ {
+ Map.MoveToRegion(Map.VisibleRegion.WithZoom(1.0 / 3));
+ }
+
+ async void ReverseGeocodeClicked(object sender, EventArgs e)
+ {
+ var addresses = await _geocoder.GetAddressesForPositionAsync(new Position(41.8902, 12.4923));
+ foreach (var ad in addresses)
+ Debug.WriteLine(ad);
+ }
+
+ void HomeClicked(object sender, EventArgs e)
+ {
+ Map.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(41.890202, 12.492049), Distance.FromMiles(0.5)));
+ }
+
+ void ZoomPinClicked(object sender, EventArgs e)
+ {
+ var pos = new Position(41.011995, -8.642995);
+ Map.Pins.Clear();
+ Map.Pins.Add(new Pin { Position = pos, Label = "Rui" });
+ Map.MoveToRegion(MapSpan.FromCenterAndRadius(pos, Distance.FromMiles(0.5)));
+ }
+
+ void EditPinClicked(object sender, EventArgs e)
+ {
+ var pin = Map.Pins.First();
+
+ pin.Label += " Edited";
+ pin.Address = "Edited";
+
+ var pos = new Position(pin.Position.Latitude + 1, pin.Position.Longitude + 1);
+ pin.Position = pos;
+ Map.MoveToRegion(MapSpan.FromCenterAndRadius(pos, Distance.FromMiles(0.5)));
+ }
+
+ void RemovePinClicked(object sender, EventArgs e)
+ {
+ Map.Pins.RemoveAt(0);
+ }
+ }
+}
\ No newline at end of file
<EmbeddedResource Update="GalleryPages\CollectionViewGalleries\DataTemplateSelectorGallery.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
+ <EmbeddedResource Update="GalleryPages\MapGallery.xaml">
+ <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
+ </EmbeddedResource>
<EmbeddedResource Update="GalleryPages\MapWithItemsSourceGallery.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
}
if (NativeMap != null)
- {
- NativeMap.MyLocationEnabled = false;
- NativeMap.SetOnCameraMoveListener(null);
- NativeMap.InfoWindowClick -= MapOnMarkerClick;
- NativeMap.Dispose();
+ {
+ NativeMap.MyLocationEnabled = false;
+ NativeMap.SetOnCameraMoveListener(null);
+ NativeMap.InfoWindowClick -= MapOnMarkerClick;
+ NativeMap.MapClick -= OnMapClick;
+ NativeMap.Dispose();
NativeMap = null;
- }
+ }
Control?.OnDestroy();
}
{
NativeMap.SetOnCameraMoveListener(null);
NativeMap.InfoWindowClick -= MapOnMarkerClick;
+ NativeMap.MapClick -= OnMapClick;
NativeMap = null;
}
map.SetOnCameraMoveListener(this);
map.InfoWindowClick += MapOnMarkerClick;
+ map.MapClick += OnMapClick;
map.UiSettings.ZoomControlsEnabled = Map.HasZoomEnabled;
map.UiSettings.ZoomGesturesEnabled = Map.HasZoomEnabled;
targetPin?.SendTap();
}
+ void OnMapClick(object sender, GoogleMap.MapClickEventArgs e)
+ {
+ Map.SendMapClicked(new Position(e.Point.Latitude, e.Point.Longitude));
+ }
+
void MoveToRegion(MapSpan span, bool animate)
{
GoogleMap map = NativeMap;
Control.MapServiceToken = FormsMaps.AuthenticationToken;
Control.ZoomLevelChanged += async (s, a) => await UpdateVisibleRegion();
Control.CenterChanged += async (s, a) => await UpdateVisibleRegion();
+ Control.MapTapped += OnMapTapped;
}
MessagingCenter.Subscribe<Map, MapSpan>(this, "MapMoveToRegion", async (s, a) => await MoveToRegion(a), mapModel);
{
Control.PanInteractionMode = Element.HasScrollEnabled ? MapPanInteractionMode.Auto : MapPanInteractionMode.Disabled;
}
+
+ void OnMapTapped(MapControl sender, MapInputEventArgs args)
+ {
+ Element?.SendMapClicked(new Position(args.Location.Position.Latitude, args.Location.Position.Longitude));
+ }
}
}
object _lastTouchedView;
bool _disposed;
+#if __MOBILE__
+ UITapGestureRecognizer _mapClickedGestureRecognizer;
+#endif
+
const string MoveMessageName = "MapMoveToRegion";
public override SizeRequest GetDesiredSize(double widthConstraint, double heightConstraint)
}
mkMapView.RemoveFromSuperview();
#if __MOBILE__
+ mkMapView.RemoveGestureRecognizer(_mapClickedGestureRecognizer);
+ _mapClickedGestureRecognizer.Dispose();
+ _mapClickedGestureRecognizer = null;
+
if (FormsMaps.IsiOs9OrNewer)
{
// This renderer is done with the MKMapView; we can put it in the pool
mapView.GetViewForAnnotation = GetViewForAnnotation;
mapView.RegionChanged += MkMapViewOnRegionChanged;
+#if __MOBILE__
+ mapView.AddGestureRecognizer(_mapClickedGestureRecognizer = new UITapGestureRecognizer(OnMapClicked));
+#endif
}
MessagingCenter.Subscribe<Map, MapSpan>(this, MoveMessageName, (s, a) => MoveToRegion(a), mapModel);
targetPin.SendTap();
}
+#if __MOBILE__
+ void OnMapClicked(UITapGestureRecognizer recognizer)
+ {
+ if (Element == null)
+ {
+ return;
+ }
+
+ var tapPoint = recognizer.LocationInView(Control);
+ var tapGPS = ((MKMapView)Control).ConvertPoint(tapPoint, Control);
+ ((Map)Element).SendMapClicked(new Position(tapGPS.Latitude, tapGPS.Longitude));
+ }
+#endif
+
void UpdateRegion()
{
if (_shouldUpdateRegion)
get { return (DataTemplateSelector)GetValue(ItemTemplateSelectorProperty); }
set { SetValue(ItemTemplateSelectorProperty, value); }
}
+
+ public event EventHandler<MapClickedEventArgs> MapClicked;
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ public void SendMapClicked(Position position) => MapClicked?.Invoke(this, new MapClickedEventArgs(position));
[EditorBrowsable(EditorBrowsableState.Never)]
public void SetVisibleRegion(MapSpan value) => VisibleRegion = value;
--- /dev/null
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Xamarin.Forms.Maps
+{
+ public class MapClickedEventArgs
+ {
+ public Position Position { get; }
+
+ public MapClickedEventArgs(Position position)
+ {
+ Position = position;
+ }
+ }
+}