Forum Xamarin.Forms

How to use device location with CustomMapRenderer?

BhaveshHiraniBhaveshHirani USMember
edited July 2017 in Xamarin.Forms

I have created a custom map and all works fine. Except that I am not able show device location on the map. The controls for zoom and current location do not appear either. I tried getting the location using Plugin.Geocoder but The map doesn't want to center to that location.

Sources: https://bitbucket.org/hirani89/xamarin-custom-maps/src/713f6d62fbf55e6775cf96d0cbed9825e95b2374?at=master

MainPage.xaml.cs

using Plugin.Geolocator;
using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Maps;

namespace CMap
{
    public partial class MainPage : ContentPage
    {
        public Map StockistMap;

        public MainPage()
        {
            InitializeComponent();
            Initialize();
            StockistMap = new Map()
            {
                IsShowingUser = true,
                HeightRequest = 800,
                WidthRequest = 960,
                IsVisible = true,
                MapType = MapType.Street,
                VerticalOptions = LayoutOptions.FillAndExpand
            };
            var position1 = new Position(36.8961, 10.1865);
            var position2 = new Position(36.891, 10.181);
            var position3 = new Position(36.892, 10.182);
            var position4 = new Position(36.893, 10.183);
            var position5 = new Position(36.891, 10.185);
            var position6 = new Position(36.892, 10.187);

            var customPin1 = new CustomPin
            {
                Pin = new Pin
                {
                    Type = PinType.Place,
                    Position = position1,
                    Label = "IntilaQ",
                    Address = "Technopark Elgazala, Tunisia"
                },
                URL = "www.intilaq.tn",
            };


            var customPin2 = new CustomPin
            {
                Pin = new Pin
                {
                    Type = PinType.SearchResult,
                    Position = position2,
                    Label = "Telnet R&D",
                    Address = "Technopark Elgazala, Tunisia"
                },
                URL = "www.groupe-telnet.com"
            };

            var customPin3 = new CustomPin
            {
                Pin = new Pin
                {
                    Type = PinType.SearchResult,
                    Position = position3,
                    Label = "Kromberg&Schubert",
                    Address = "Technopark Elgazala, Tunisia"
                },
                URL = "www.kromberg-schubert.com"
            };

            var customPin4 = new CustomPin
            {
                Pin = new Pin
                {
                    Type = PinType.SearchResult,
                    Position = position4,
                    Label = "Via Mobile",
                    Address = "Technopark Elgazala, Tunisia"
                },
                URL = "www.kromberg-schubert.com"
            };

            var customPin5 = new CustomPin
            {
                Pin = new Pin
                {
                    Type = PinType.SearchResult,
                    Position = position5,
                    Label = "Via Mobile",
                    Address = "Technopark Elgazala, Tunisia"
                },
                URL = "www.kromberg-schubert.com"
            };

            var customPin6 = new CustomPin
            {
                Pin = new Pin
                {
                    Type = PinType.SearchResult,
                    Position = position6,
                    Label = "Via Mobile",
                    Address = "Technopark Elgazala, Tunisia"
                },
                URL = "www.kromberg-schubert.com"
            };

            StockistMap.Pins.Add 
            (
                customPin1.Pin
            );

            MapContainer.Children.Add(StockistMap);
        }
        private async void Initialize()
        {
            await RetrieveLocation();
        }
        private async Task RetrieveLocation()
        {
            try
            {
                var locator = CrossGeolocator.Current;
                locator.DesiredAccuracy = 50;

                var position = await locator.GetPositionAsync(TimeSpan.FromSeconds(10));
                StockistMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(position.Latitude, position.Longitude), Distance.FromKilometers(10)));

            }
            catch (Exception ex)
            {
                Debug.WriteLine("Unable to get location, may need to increase timeout: " + ex);
            }
        }
    }
}

CustomMap.cs

using System.Collections.Generic;
using Xamarin.Forms.Maps;

namespace CMap
{
    public class CustomMap : Map
    {
        public List<CustomPin> CustomPins { get; set; }
    }
}

CustomPin.cs

    using System;
    using Xamarin.Forms.Maps;

    namespace CMap
    {
        public class CustomPin
        {
            public Pin Pin { get; set; }
            public String URL { get; set; }
        }
    }

CustomMapRenderer.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using CMap;
using CMap.Droid.Platform;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using Xamarin.Forms.Platform.Android;

[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CMap.Droid.Platform
{
    public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter, IOnMapReadyCallback
    {
        private GoogleMap _map;
        private List<CustomPin> _customPins;
        private bool _isDrawn;

        protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                _map.InfoWindowClick -= OnInfoWindowClick;
            }

            if (e.NewElement != null)
            {
                var formsMap = (CustomMap)e.NewElement;

                _customPins = formsMap.CustomPins;

                ((MapView)Control).GetMapAsync(this);
            }
        }

        public void OnMapReady(GoogleMap googleMap)
        {
            _map = googleMap;
            _map.InfoWindowClick += OnInfoWindowClick;
            _map.SetInfoWindowAdapter(this);
        }

        protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);

            if (e.PropertyName.Equals("VisibleRegion") && !_isDrawn)
            {
                _map.Clear();

                foreach (var pin in _customPins)
                {
                    var marker = new MarkerOptions();

                    marker.SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude));

                    marker.SetTitle(pin.Pin.Label);

                    marker.SetSnippet(pin.Pin.Address);

                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));

                    _map.AddMarker(marker);
                }

                _isDrawn = true;
            }
        }

        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);

            if (changed)
            {
                _isDrawn = false;
            }
        }

        void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
        {
            var customPin = GetCustomPin(e.Marker);

            if (customPin == null)
            {
                throw new Exception("Custom pin not found");
            }

            if (!string.IsNullOrWhiteSpace(customPin.URL))
            {
                var url = Android.Net.Uri.Parse(customPin.URL);

                var intent = new Intent(Intent.ActionView, url);

                intent.AddFlags(ActivityFlags.NewTask);

                Android.App.Application.Context.StartActivity(intent);
            }
        }

        public Android.Views.View GetInfoContents(Marker marker)
        {
            var inflater = Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as Android.Views.LayoutInflater;

            if (inflater != null)
            {
                Android.Views.View view;

                var customPin = GetCustomPin(marker);
                if (customPin == null)
                {
                    throw new Exception("Custom pin not found");
                }

                view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);

                var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
                var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);

                if (infoTitle != null)
                {
                    infoTitle.Text = marker.Title;
                }
                if (infoSubtitle != null)
                {
                    infoSubtitle.Text = marker.Snippet;
                }

                return view;
            }
            return null;
        }

        public Android.Views.View GetInfoWindow(Marker marker)
        {
            return null;
        }

        CustomPin GetCustomPin(Marker annotation)
        {
            var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);

            foreach (var pin in _customPins)
            {
                if (pin.Pin.Position == position)
                {
                    return pin;
                }
            }
            return null;
        }
    }
}

Answers

  • dano_jidano_ji PKMember

    var loc = CrossGeolocator.Current;
    loc.DesiredAccuracy = 20;
    var pos = await loc.GetPositionAsync(10000);
    customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(position.Latitude, position.Longitude), Distance.FromMiles(1.0)));

    use this code.

Sign In or Register to comment.