Xamarin Forms Maps - how to refresh/update the map - CustomMap Renderer

前端 未结 4 2013
予麋鹿
予麋鹿 2021-02-06 14:06

If you are searching for a full polylines, pins, tiles, UIOptions (and 3D effects soon) renderings/implementations, you should take a loot at the public github I made at

4条回答
  •  半阙折子戏
    2021-02-06 14:12

    The custom renderer from the example is not made for dynamic updating the path. It is just implemented for the case, where all points of the paths are known before initializing the map / drawing the path the first time. So you have this race condition, you ran into, because you are loading the directions from a web service.

    So you have to do some changes:

    RouteCoordinates must be a BindableProperty

    public class CustomMap : Map
    {
        public static readonly BindableProperty RouteCoordinatesProperty =
            BindableProperty.Create>(p => p.RouteCoordinates, new List());
    
        public List RouteCoordinates
        {
            get { return (List)GetValue(RouteCoordinatesProperty); }
            set { SetValue(RouteCoordinatesProperty, value); }
        }
    
        public CustomMap ()
        {
            RouteCoordinates = new List();
        }
    }
    

    Update the Polyline whenever the coordinates change

    • Move the creation of the polyline from OnMapReady to UpdatePolyLine
    • call UpdatePolyLine from OnMapReady and OnElementPropertyChanged
    public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback
    {
        GoogleMap map;
        Polyline polyline;
    
        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs e)
        {
            base.OnElementChanged(e);
    
            if (e.OldElement != null)
            {
                // Unsubscribe
            }
    
            if (e.NewElement != null)
            {
                ((MapView)Control).GetMapAsync(this);
            }
        }
    
        protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged(sender, e);
            if (this.Element == null || this.Control == null)
                return;
    
            if (e.PropertyName == CustomMap.RouteCoordinatesProperty.PropertyName)
            {
                UpdatePolyLine();
            }
        }
    
        private void UpdatePolyLine()
        {
            if (polyline != null)
            {
                polyline.Remove();
                polyline.Dispose();
            }               
    
            var polylineOptions = new PolylineOptions();
            polylineOptions.InvokeColor(0x66FF0000);
    
            foreach (var position in ((CustomMap)this.Element).RouteCoordinates)
            {
                polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
            }
    
            polyline = map.AddPolyline(polylineOptions);
        }
    
        public void OnMapReady(GoogleMap googleMap)
        {
            map = googleMap;
            UpdatePolyLine();
        }
    }
    

    Setting the data

    Updating the positions changes a bit. Instead of adding the positions to the existing list, you have to (create a new list) and set it to RouteCoordinates. You can use Device.BeginInvokeOnMainThread to ensure, that the operation is performed on the UI thread. Else the polyline will not update.

    Device.BeginInvokeOnMainThread(() =>
    {
        customMap.RouteCoordinates = new List
        {
            new Position (37.797534, -122.401827),
            new Position (37.776831, -122.394627)
        };
    }) 
    

    In your case it's something like

    var list = new List(customMap.RouteCoordinates);
    list.Add(directionMap.address_end.position);
    customMap.RouteCoordinates = list;
    

    Todo

    On iOS you have now to implement a similar behavior (like UpdatePolyLine)

    Note

    That might not the most performant implementation, because you redraw everything instead of adding one point. But it's fine as long as you have no performance issues :)

提交回复
热议问题