简体   繁体   English

不刷新自定义渲染器Xamarin表单地图

[英]Not refreshing custom renderer Xamarin forms maps

I created a map with custom marker with real-time location update. 我使用自定义标记创建了具有实时位置更新的地图。 But after adding a new pin to the map its not applying the custom renderer. 但是在向地图添加新的图钉后,它不会应用自定义渲染器。 If I zoomed-in or zoomed-out on the map its applying that custom renders for markers. 如果在地图上放大或缩小,则其将应用自定义标记渲染。 Here is my code. 这是我的代码。

This Code is in Xamarin.Droid project 该代码在Xamarin.Droid项目中

     public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback, GoogleMap.IInfoWindowAdapter
{

    GoogleMap map;
    List<Position> routeCoordinates;
    List<CustomPin> customPins;
    Action<CustomPin> onInfoWindowClicked;


    public void OnMapReady(GoogleMap googleMap)
    {
        map = googleMap;

        //map.InfoWindowClick += OnInfoWindowClick;
        map.SetInfoWindowAdapter(this);

        var polylineOptions = new PolylineOptions();
        polylineOptions.InvokeColor(Android.Graphics.Color.Blue);

        foreach (var position in routeCoordinates)
        {
            polylineOptions.Add(new LatLng(position.Latitude, position.Longitude));
        }

        map.AddPolyline(polylineOptions);

    }

    protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Xamarin.Forms.View> e)
    {
        base.OnElementChanged(e);

        if (e.OldElement != null)
        {
            map.InfoWindowClick -= OnInfoWindowClick;
            // Unsubscribe
        }

        if (e.NewElement != null)
        {

            var formsMap = (CustomMap)e.NewElement;

            routeCoordinates = formsMap.RouteCoordinates;
            customPins = formsMap.CustomPins;
            onInfoWindowClicked = formsMap.OnInfoWindowClicked;
            ((Android.Gms.Maps.MapView)Control).GetMapAsync(this);
        }
    }

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

        if (map != null)
        {
            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.Id.ToString());
                marker.SetSnippet(pin.Pin.Address);

                if(pin.UserType == global::Common.Models.UserType.Driver)
                {
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.car));
                }

                else if (pin.UserType == global::Common.Models.UserType.Rider)
                {
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.person));
                }

                map.AddMarker(marker);
            }

        }
    }

    void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
    {
        onInfoWindowClicked(GetCustomPin(e.Marker));
    }

    private CustomPin GetCustomPin(Marker marker)
    {
        return customPins.Find(x => x.Id.ToString() ==marker.Title.ToString());
    }

    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 infoImage = view.FindViewById<ImageView>(Resource.Id.markerInfoImage);
            var infoTitle = view.FindViewById<TextView>(Resource.Id.markerInfoTitle);
            var infoSummary = view.FindViewById<TextView>(Resource.Id.markerInfoSummary);



            System.IO.Stream ims = Context.Assets.Open(customPin.Image);

            // load image as Drawable
            Drawable d = Drawable.CreateFromStream(ims, null);

            // set image to ImageView
            infoImage.SetImageDrawable(d);


            //File file = new File(customPin.Image);
            //var image  = Android.Net.Uri.FromFile(file);
            //var resource=ResourceManager.GetDrawableByName("driverLogActive_icon.png");
            //infoImage.SetImageResource(resource);
            //infoImag = customPin.Title;

            infoTitle.Text = customPin.Title;

            infoSummary.Text = customPin.MobileNo;

            return view;
        }
        return null;
    }

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

This code is in Xamarin.Forms project 这段代码在Xamarin.Forms项目中

    public class CustomPin
{
    public Pin Pin { get; set; }
    public Guid Id { get; set; }
    public string Title { get; set; }
    public string MobileNo { get; set; }
    public string Image { get; set; }
    public string UserName { get; set; }
    public UserType UserType { get; set; }
}

public class CustomMap : Map
{
    public static readonly BindableProperty RouteCoordinatesProperty = BindableProperty.Create(nameof(RouteCoordinates), typeof(List<Position>), typeof(CustomMap), new List<Position>(), BindingMode.TwoWay);
    public static readonly BindableProperty CustomPinsProperty = BindableProperty.Create(nameof(CustomPins), typeof(List<CustomPin>), typeof(CustomMap), new List<CustomPin>(), BindingMode.TwoWay);



    public List<CustomPin> CustomPins
    {
        get { return (List<CustomPin>)GetValue(CustomPinsProperty); }
        set { SetValue(CustomPinsProperty, value); }
    }

    public List<Position> RouteCoordinates
    {
        get { return (List<Position>)GetValue(RouteCoordinatesProperty); }
        set { SetValue(RouteCoordinatesProperty, value); }
    }

    public Action<CustomPin> OnInfoWindowClicked;

    public CustomMap()
    {
        RouteCoordinates = new List<Position>();
        CustomPins = new List<CustomPin>();
    }
}

This is how I use the custom map to render pin in Xamrin.Fomrs project 这就是我使用自定义地图在Xamrin.Fomrs项目中渲染图钉的方式

    private void RenderPin(string longitudeCoordinate, string latitudeCoordinate,bool canMoveToLoacation, string lable,UserType userType,string mobileNo,string image,string userName)
    {
        double latitude = 0;
        double longitude = 0;

        double.TryParse(latitudeCoordinate, out latitude);
        double.TryParse(longitudeCoordinate, out longitude);

        var position = new Position(latitude, longitude);

        var pin = new CustomPin
        {
            Pin = new Pin
            {
                Type = PinType.Place,
                Position = position,
                Label = lable,
            },
            Title = lable,
            UserType = userType,
            MobileNo = "Mobile No:" + mobileNo,
            Image = "profile_images/" + image,
            UserName = userName,
            Id = Guid.NewGuid()
        };


        map.CustomPins.Add(pin);
        map.Pins.Add(pin.Pin);
        if (canMoveToLoacation)
        {
            map.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(latitude, longitude), Distance.FromKilometers(2)));
        }
    }

If you install the Xamarin.Forms.Maps pre-release ( 2.3.5.255-pre5 ), you can now just override the CreateMarker() method in MapRenderer . 如果您安装了Xamarin.Forms.Maps的预发行版( 2.3.5.255-pre5 ),则现在可以重写MapRendererCreateMarker()方法。 It's much more elegant, and it fixes this problem with pins not being updated when added after map creation. 它更加优雅,并且解决了此问题,在创建地图后添加图钉时不更新图钉。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM