我有一个使用Xamarin Form的跨平台应用程序,需要在地图上显示一堆自定义图钉。
在iOS上一切正常的情况下:
我在android上遇到了一些麻烦:
您可以看到自定义地图图钉显示在常规图钉上,这是自定义渲染器类:
using System;
using System.Collections.Generic;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Hangover.Droid.CustomRenderer;
using Hangover.View;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(map_mappaPersonalizzata), typeof(android_mappaPersonalizzata))]
namespace Hangover.Droid.CustomRenderer
{
public class android_mappaPersonalizzata : MapRenderer
{
private static bool test = true;
List<view_PinHangover> customPins;
map_mappaPersonalizzata formsMap;
public android_mappaPersonalizzata(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var crossMapPlatform = (map_mappaPersonalizzata)e.NewElement;
this.customPins = crossMapPlatform.datasource;
Control.GetMapAsync(this);
}
}
/// <summary>
/// Restituisce l'ID DI un pin in base al tipo
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private int getPinID(String url)
{
if (url.Equals("drawable/map_clubBenefit.png"))
return Resource.Drawable.map_clubBenefit;
else
return Resource.Drawable.map_club;
}
/// <summary>
/// Metodo chiamato quando la mappa è pronta
/// </summary>
/// <param name="googleMap">Google map.</param>
override protected void OnMapReady(GoogleMap googleMap)
{
base.OnMapReady(googleMap);
formsMap = (map_mappaPersonalizzata)Element; // mappa cross platform
var nativeMap = googleMap; // mappa nativa utilizzabile
nativeMap.MyLocationEnabled = formsMap.IsShowingUser;
nativeMap.InfoWindowClick += OnInfoWindowClick;
var items = formsMap.datasource;
foreach (var item in items)
{
var markerWithIcon = new MarkerOptions();
markerWithIcon.SetPosition(new LatLng(item.evento.Lat, item.evento.Long));
markerWithIcon.SetTitle(item.evento.NomeEvento + " - " + item.evento.getPrezzo);
markerWithIcon.SetSnippet(item.getRating);
markerWithIcon.SetIcon(BitmapDescriptorFactory.FromResource(this.getPinID(item.icon)));
nativeMap.AddMarker(markerWithIcon);
}
}
/// <summary>
/// Gestisce la selezione di un elemento della mappa
/// </summary>
/// <param name="sender">Sender.</param>
/// <param name="e">E.</param>
void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
{
var customPin = getCustomPin(e.Marker);
formsMap.gestisciOperazioneSchermata(customPin.evento);
}
/// <summary>
/// Ottiene il pin corrispondente a partire da una annotazione
/// </summary>
/// <returns>The custom pin.</returns>
/// <param name="annotation">Annotation.</param>
view_PinHangover 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;
}
}
}
I'm really having trouble understanding why is rendered this way,
thanks for the help.
**Edit**
So found the problem : in order to add the custom marker you have to override the method:
protected override MarkerOptions CreateMarker(Pin pin)
I was adding the custom marker in the wrong method and that caused the double pin on the map, so if Anyone is wondering , here is the full piece of code :
using System;
using System.Collections.Generic;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Hangover.Droid.CustomRenderer;
using Hangover.View;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(map_mappaPersonalizzata), typeof(android_mappaPersonalizzata))]
namespace Hangover.Droid.CustomRenderer
{
public class android_mappaPersonalizzata : MapRenderer, GoogleMap.IInfoWindowAdapter
{
private static bool test = true;
List<view_PinHangover> customPins;
map_mappaPersonalizzata formsMap;
public android_mappaPersonalizzata(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var crossMapPlatform = (map_mappaPersonalizzata)e.NewElement;
this.customPins = crossMapPlatform.datasource;
Control.GetMapAsync(this);
}
}
/// <summary>
/// Metodo chiamato quando la mappa è pronta
/// </summary>
/// <param name="googleMap">Google map.</param>
override protected void OnMapReady(GoogleMap googleMap)
{
base.OnMapReady(googleMap);
formsMap = (map_mappaPersonalizzata)Element; // mappa cross platform
var nativeMap = googleMap; // mappa nativa utilizzabile
nativeMap.SetInfoWindowAdapter(this);
nativeMap.MyLocationEnabled = formsMap.IsShowingUser;
nativeMap.InfoWindowClick += OnInfoWindowClick;
}
/// <summary>
/// Crea il marker personalizzato sulla mappa cercando quello personalizzato
/// nel datasource della mappa personalizzata
/// </summary>
/// <param name="pin"></param>
/// <returns></returns>
protected override MarkerOptions CreateMarker(Pin pin)
{
var marker = new MarkerOptions();
var customMarker = getCustomPin(pin.Position.Latitude, pin.Position.Longitude);
if (customMarker == null)
return null;
marker.SetPosition(new LatLng(customMarker.Position.Latitude, customMarker.Position.Longitude));
marker.SetTitle(customMarker.evento.NomeEvento + " - " + customMarker.evento.getPrezzo);
marker.SetSnippet(customMarker.getRating);
marker.SetIcon(BitmapDescriptorFactory.FromResource(this.getPinID(customMarker.icon)));
return marker;
}
/// <summary>
/// Restituisce l'ID DI un pin in base al tipo
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private int getPinID(String url)
{
if (url.Equals("drawable/map_clubBenefit.png"))
return Resource.Drawable.map_clubBenefit;
else
return Resource.Drawable.map_club;
}
/// <summary>
/// Gestisce la selezione di un elemento della mappa
/// </summary>
/// <param name="sender">Sender.</param>
/// <param name="e">E.</param>
void OnInfoWindowClick(object sender, GoogleMap.InfoWindowClickEventArgs e)
{
var customPin = getCustomPin(e.Marker.Position.Latitude,e.Marker.Position.Longitude);
formsMap.gestisciOperazioneSchermata(customPin.evento);
}
/// <summary>
/// Ottiene il pin corrispondente a partire da una annotazione
/// </summary>
/// <returns>The custom pin.</returns>
/// <param name="annotation">Annotation.</param>
view_PinHangover getCustomPin(double lat,double longitude)
{
var position = new Position(lat, longitude);
foreach (var pin in customPins)
{
if (pin.Position == position)
{
return pin;
}
}
return null;
}
public Android.Views.View GetInfoContents(Marker marker)
{
return null;
}
public Android.Views.View GetInfoWindow(Marker marker)
{
return null;
}
}
}
答案 0 :(得分:1)
我可以尝试custom map,它可以正常工作,因此请按照以下代码修改您的代码。
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;
}