Search code examples
mapsxamarin.formszooming

Xamarin Forms Maps - How to get the value of the Zoom and add a listener on it?


I think that everything is in the title, I'm working with a PCL logic

Thank in advance !


Solution

  • I then found a solution !

    You have so your map, which inherit from the Xamarin Map Control:

    public class CustomMap : Map
    {
        // Your others properties
    
        public static readonly BindableProperty ZoomLevelProperty =
            BindableProperty.Create(nameof(ZoomLevel), typeof(Distance), typeof(CustomMap), new Distance());
        public Distance ZoomLevel
        {
            get { return (Distance)GetValue(ZoomLevelProperty); }
            set { SetValue(ZoomLevelProperty, value); }
        }
    
        #region Constructor
        public CustomMap()
        {
            this.PropertyChanged += (object sender, PropertyChangedEventArgs e) =>
            {
                CustomMap map = sender as CustomMap;
                if (map.VisibleRegion != null)
                {
                    this.ZoomLevel = map.VisibleRegion.Radius;
                    Debug.WriteLine("Xamarin Forms Map Radius: {0} Kilometers | {1} Meters | {2} Miles.", ZoomLevel.Kilometers, ZoomLevel.Meters, ZoomLevel.Miles);
                }
            };
        }
        #endregion
    }
    

    Let me explain:

    So, once you've defined your CustomMap, you have to add a Zoom property as I do. This property have to be a Distance type. Now, how to set it? in the constructor, by example, you can do like me. For each gesture on the map, your zoom property will be set and then, you can work with km, meters and miles.

    Note: However, it doesn't seem that ZoomLevel is set in the constructor, it seems to need at least one gesture, but I'm working on it and I'll edit my answer later !

    If you need to edit something in a Renderer each time the zoom is set, you can do something like below: (UWP example, but it's kind of the same for others Android/iOS)

    [assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
    namespace Project.UWP.CustomRenderer
    {
        public class CustomMapRenderer : MapRenderer
        {
            MapControl nativeMap;
            CustomMap customMap;
    
            protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
            {
                base.OnElementChanged(e);
    
                if (e.NewElement != null)
                {
                    customMap = (CustomMap)e.NewElement;
                    nativeMap = Control as MapControl;
                }
            }
    
            protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
            {
                base.OnElementPropertyChanged(sender, e);
    
                if (this.Element == null || this.Control == null)
                    return;
    
                //From here, each time the zoom is set you going into the if()
                if (e.PropertyName == CustomMap.ZoomLevelProperty.PropertyName)
                    ZoomSetted();
            }
    
            private void ZoomSetted()
            {
                if (customMap != null && nativeMap != null)
                {
                    Debug.WriteLine("Hello World ! You can access the zoom like that =>"); 
                    Debug.WriteLine("Xamarin Forms Map Radius: {0} Kilometers | {1} Meters | {2} Miles.", 
                        customMap.ZoomLevel.Kilometers, 
                        customMap.ZoomLevel.Meters, 
                        customMap.ZoomLevel.Miles);
                }
            }
        }
    }