简体   繁体   中英

Xamarin Forms - custom map marker not visible

I am following article on MS page about Custom map renderer and I can not get it to work for android. Map shows but pins (Markers) are not there. I did not found what I did different from official documents (as in previous link). When I debug, there are 3 markers in customPins collection. And custom renderer works in UWP. So issue is only in Android code.

Here is my CustomRender code for Android which does not shows pins.

using System;
using System.Collections.Generic;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using iVanApp;
using iVanApp.Android.CustomMapRenderers;
using iVanApp.Droid;
using iVanApp.Model;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;

[assembly: ExportRenderer(typeof(NightMap), typeof(MapRenderers))]

namespace iVanApp.Android.CustomMapRenderers
{
    public class MapRenderers : MapRenderer, GoogleMap.IInfoWindowAdapter
    {
        List<NightPin> customPins;

        public MapRenderers(Context context) : base(context)
        {
        }
        protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
        {
            base.OnElementChanged(e);

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

            if (e.NewElement != null)
            {
                var formsMap = (NightMap)e.NewElement;
                customPins = formsMap.NightPins;
            }
        }
        protected override void OnMapReady(GoogleMap map)
        {
            base.OnMapReady(map);

            NativeMap.InfoWindowClick += OnInfoWindowClick;
            
            NativeMap.SetInfoWindowAdapter(this);
        }

        protected override MarkerOptions CreateMarker(Pin pin)
        {
            var marker = new MarkerOptions();
            marker.SetPosition(new LatLng(pin.Position.Latitude, pin.Position.Longitude));
            marker.SetTitle(pin.Label);
            marker.SetSnippet(pin.Address);
            marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
            
            return marker;
        }
        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.Name))
            {

            }
        }



        NightPin GetCustomPin(Marker annotation)
        {
            var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);
            foreach (var pin in customPins)
            {
                if (pin.Position == position)
                {
                    return pin;
                }
            }
            return null;
        }

        public global::Android.Views.View GetInfoContents(Marker marker)
        {
            var inflater = global::Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as global::Android.Views.LayoutInflater;
            if (inflater != null)
            {
                global::Android.Views.View view;

                var customPin = GetCustomPin(marker);
                if (customPin == null)
                {
                    throw new Exception("Custom pin not found");
                }
                view = inflater.Inflate(Resource.Layout.mtrl_layout_snackbar_include, null);
                if (customPin.Name.Equals("Xamarin"))
                {
                    view = inflater.Inflate(Resource.Layout.XamarinMapInfoWindow, null);
                }
                else
                {
                    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 global::Android.Views.View GetInfoWindow(Marker marker)
        {
            return null;
        }


    }
}

DOes anyone have idea why this would not work?

Note: I had to modify official MS code because I got errors. Wherever is Android.Views.View I had to modify it to global::Android.Views.View otherwise I got following error

"'MapRenderers' does not implement interface member 'GoogleMap.IInfoWindowAdapter.GetInfoContents(Marker)'. 'MapRenderers.GetInfoContents(Marker)' cannot implement 'GoogleMap.IInfoWindowAdapter.GetInfoContents(Marker)' because it does not have the matching return type of 'View'.".

and

The type or namespace name 'Views' does not exist in the namespace 'iVanApp.Android' (are you missing an assembly reference?)

Hope this did not break my code.

After investigating and reading about custom map issues (and mostly solutions) from others I got a workaround solution how to get pins on map but does not show info window when I click on pin(marker). Here I found workaround . If I modify OnMapReday and call&add method SetMapMarkers then pins are visible but as I said no info window is shown when I click on pin

protected override void OnMapReady(GoogleMap map)
    {
        base.OnMapReady(map);

        NativeMap.InfoWindowClick += OnInfoWindowClick;
        
        NativeMap.SetInfoWindowAdapter(this);
        SetMapMarkers();
    }       

private void SetMapMarkers()
        {
            NativeMap.Clear();

            foreach (var pin in customPins)
            {
                NativeMap.AddMarker(CreateMarker(pin));
            }
        }

Although this is solution, I would prefer if I could get it to work without this workaround. Hence I did not put much effort why info window is not shown when you click on pin. In case there would be no solution without this workaround then I will be interested in solution with workaround but as I said I do not prefer to go this way.

As FreakyAli said that adding a custom pin and positions for CustomMap.

  <local:CustomMap x:Name="customMap" MapType="Street" />

Adding a custom pin and positions the map's view with the MoveToRegion method

 public  MainPage()
    {
        InitializeComponent();
        var pin = new CustomPin
        {
            Type = PinType.Place,
            Position = new Position(37.79752, -122.40183),
            Label = "Xamarin San Francisco Office",
            Address = "394 Pacific Ave, San Francisco CA",
            Id = "Xamarin",
            Url = "http://xamarin.com/about/"
        };

        customMap.CustomPins = new List<CustomPin> { pin };
        customMap.Pins.Add(pin);
        customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.79752, -122.40183), Distance.FromMiles(1.0)));

    }

I can get InfoWindow by clicking map pin, having no problem.

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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