设置自定义标记图像将覆盖默认标记图标和自定义图标
Setting custom marker image would overlay default marker icon along with custom icon
将表单版本更新到 2.4.0.282 后,我开始在 MapView
中遇到这种奇怪的行为。我在 android 中为地图创建了一个自定义渲染器,我根据自己的要求在其中设置标记图像。自定义标记实际上出现了,但在它上面,它的默认图标仍然被覆盖。
请注意,我使用的是 Xamarin.Maps 版本 2.4.0.282,我也尝试过降级到以前的版本,但没有任何帮助。
我什至通过评论行试过了,
Forms.SetFlags("FastRenderers_Experimental");
但即使这样也无济于事。
下面是我创建的渲染器,
public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback
{
GoogleMap map;
public static double PreviousDistance = 0;
List<CustomPin> customPins;
CustomMap formsMap = null;
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
map.InfoWindowClick -= OnInfoWindowClick;
map.MarkerClick -= OnMarkerClick;
}
if (e.NewElement != null)
{
formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
((MapView)Control).GetMapAsync(this);
}
}
protected override void OnMapReady(GoogleMap googleMap)
{
map = googleMap;
map.InfoWindowClick += OnInfoWindowClick;
map.MarkerClick += OnMarkerClick;
map.UiSettings.ZoomControlsEnabled = false;
formsMap.MoveToRegion(MapSpan.FromCenterAndRadius(formsMap.Location, Distance.FromMiles(1.0)));
if(customPins != null && customPins.Count > 0)
{
setMapPins("CustomPins");
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "CustomPins" || (e.PropertyName.Equals("VisibleRegion")))
{
setMapPins(e.PropertyName);
}
}
private void setMapPins(string PropertyName)
{
customPins = formsMap.CustomPins;
map.Clear();
if (customPins != null && customPins.Count > 0)
{
if (PropertyName == "CustomPins")
{
//Set map zoom
var defaultZoom = 14;
try
{
PreviousDistance = DistanceCalculation.MoveToRegionData.MoveToRegion(formsMap, customPins, defaultZoom, PreviousDistance);
}
catch (Exception ex)
{
PreviousDistance = 0;
Console.WriteLine(ex.Message);
}
}
foreach (var pin in customPins)
{
var pinImage = Resources.GetIdentifier(pin.PinImage.ToLower(), "drawable", Context.PackageName);
var markerImg = BitmapDescriptorFactory.FromResource(pinImage);
map.AddMarker(new MarkerOptions().SetTitle(pin.Pin.Label).SetSnippet(pin.Id).SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude)).SetIcon(markerImg));
}
}
else
{
Console.WriteLine("In else!!");
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
if (changed)
{
}
}
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.Url))
{
var url = global::Android.Net.Uri.Parse(customPin.Url);
var intent = new Intent(Intent.ActionView, url);
intent.AddFlags(ActivityFlags.NewTask);
global::Android.App.Application.Context.StartActivity(intent);
}
}
CustomPin GetCustomPin(Marker annotation)
{
var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);
foreach (var pin in customPins)
{
if (pin.Pin.Position == position)
{
return pin;
}
}
return null;
}
void OnMarkerClick(object sender, GoogleMap.MarkerClickEventArgs ea)
{
var marker = (Marker) ea.Marker;
formsMap.IsPinClicked = false;
var customPin = GetCustomPin(marker);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
formsMap.SelectedPinId = Convert.ToInt32(marker.Snippet);
formsMap.IsPinClicked = true;
}
}
这是现在的样子..
I have created a custom renderer for map in android where I am setting marker images as per my requirement. Custom markers in fact appear, but on top of it, it's default icon still gets overlaid.
我做了一个演示并重现了这个问题,经过一些测试我发现覆盖OnMapReady
函数导致了这个问题。即使完全为空 OnMapReady
也会出现问题。我的猜测是在自定义地图渲染中调用 OnMapReady
可能会导致重新渲染地图,包括图钉。
解法:
- 评论
OnMapReady
出来。
- 将
OnMapReady
中的逻辑移动到OnElementChanged
。
- 让您的局部变量
map=NativeMap
并确保 setMapPins
在 OnElementPropertyChanged
中被调用。
在 OnElementPropertyChanged 中添加 NativeMap.Clear(); 然后重试。希望对你有帮助!!!
查看下面用于在 Android 平台上自定义 pin 的代码。
[assembly:ExportRenderer (typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.Droid
{
public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
{
List<CustomPin> customPins;
bool isDrawn;
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
((MapView)Control).GetMapAsync(this);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName.Equals("VisibleRegion") && !isDrawn)
{
NativeMap.Clear();
NativeMap.InfoWindowClick += OnInfoWindowClick;
NativeMap.SetInfoWindowAdapter(this);
foreach (var pin in customPins)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude));
marker.SetTitle(pin.Pin.Label);
marker.SetSnippet(pin.Pin.Address);
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
NativeMap.AddMarker(marker);
}
isDrawn = true;
}
}
}
}
更多详情Click here
将表单版本更新到 2.4.0.282 后,我开始在 MapView
中遇到这种奇怪的行为。我在 android 中为地图创建了一个自定义渲染器,我根据自己的要求在其中设置标记图像。自定义标记实际上出现了,但在它上面,它的默认图标仍然被覆盖。
请注意,我使用的是 Xamarin.Maps 版本 2.4.0.282,我也尝试过降级到以前的版本,但没有任何帮助。
我什至通过评论行试过了,
Forms.SetFlags("FastRenderers_Experimental");
但即使这样也无济于事。
下面是我创建的渲染器,
public class CustomMapRenderer : MapRenderer, IOnMapReadyCallback
{
GoogleMap map;
public static double PreviousDistance = 0;
List<CustomPin> customPins;
CustomMap formsMap = null;
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Map> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
map.InfoWindowClick -= OnInfoWindowClick;
map.MarkerClick -= OnMarkerClick;
}
if (e.NewElement != null)
{
formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
((MapView)Control).GetMapAsync(this);
}
}
protected override void OnMapReady(GoogleMap googleMap)
{
map = googleMap;
map.InfoWindowClick += OnInfoWindowClick;
map.MarkerClick += OnMarkerClick;
map.UiSettings.ZoomControlsEnabled = false;
formsMap.MoveToRegion(MapSpan.FromCenterAndRadius(formsMap.Location, Distance.FromMiles(1.0)));
if(customPins != null && customPins.Count > 0)
{
setMapPins("CustomPins");
}
}
protected override void OnElementPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == "CustomPins" || (e.PropertyName.Equals("VisibleRegion")))
{
setMapPins(e.PropertyName);
}
}
private void setMapPins(string PropertyName)
{
customPins = formsMap.CustomPins;
map.Clear();
if (customPins != null && customPins.Count > 0)
{
if (PropertyName == "CustomPins")
{
//Set map zoom
var defaultZoom = 14;
try
{
PreviousDistance = DistanceCalculation.MoveToRegionData.MoveToRegion(formsMap, customPins, defaultZoom, PreviousDistance);
}
catch (Exception ex)
{
PreviousDistance = 0;
Console.WriteLine(ex.Message);
}
}
foreach (var pin in customPins)
{
var pinImage = Resources.GetIdentifier(pin.PinImage.ToLower(), "drawable", Context.PackageName);
var markerImg = BitmapDescriptorFactory.FromResource(pinImage);
map.AddMarker(new MarkerOptions().SetTitle(pin.Pin.Label).SetSnippet(pin.Id).SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude)).SetIcon(markerImg));
}
}
else
{
Console.WriteLine("In else!!");
}
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
base.OnLayout(changed, l, t, r, b);
if (changed)
{
}
}
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.Url))
{
var url = global::Android.Net.Uri.Parse(customPin.Url);
var intent = new Intent(Intent.ActionView, url);
intent.AddFlags(ActivityFlags.NewTask);
global::Android.App.Application.Context.StartActivity(intent);
}
}
CustomPin GetCustomPin(Marker annotation)
{
var position = new Position(annotation.Position.Latitude, annotation.Position.Longitude);
foreach (var pin in customPins)
{
if (pin.Pin.Position == position)
{
return pin;
}
}
return null;
}
void OnMarkerClick(object sender, GoogleMap.MarkerClickEventArgs ea)
{
var marker = (Marker) ea.Marker;
formsMap.IsPinClicked = false;
var customPin = GetCustomPin(marker);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
formsMap.SelectedPinId = Convert.ToInt32(marker.Snippet);
formsMap.IsPinClicked = true;
}
}
这是现在的样子..
I have created a custom renderer for map in android where I am setting marker images as per my requirement. Custom markers in fact appear, but on top of it, it's default icon still gets overlaid.
我做了一个演示并重现了这个问题,经过一些测试我发现覆盖OnMapReady
函数导致了这个问题。即使完全为空 OnMapReady
也会出现问题。我的猜测是在自定义地图渲染中调用 OnMapReady
可能会导致重新渲染地图,包括图钉。
解法:
- 评论
OnMapReady
出来。 - 将
OnMapReady
中的逻辑移动到OnElementChanged
。 - 让您的局部变量
map=NativeMap
并确保setMapPins
在OnElementPropertyChanged
中被调用。
在 OnElementPropertyChanged 中添加 NativeMap.Clear(); 然后重试。希望对你有帮助!!!
查看下面用于在 Android 平台上自定义 pin 的代码。
[assembly:ExportRenderer (typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.Droid
{
public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
{
List<CustomPin> customPins;
bool isDrawn;
protected override void OnElementChanged(Xamarin.Forms.Platform.Android.ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
NativeMap.InfoWindowClick -= OnInfoWindowClick;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
((MapView)Control).GetMapAsync(this);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName.Equals("VisibleRegion") && !isDrawn)
{
NativeMap.Clear();
NativeMap.InfoWindowClick += OnInfoWindowClick;
NativeMap.SetInfoWindowAdapter(this);
foreach (var pin in customPins)
{
var marker = new MarkerOptions();
marker.SetPosition(new LatLng(pin.Pin.Position.Latitude, pin.Pin.Position.Longitude));
marker.SetTitle(pin.Pin.Label);
marker.SetSnippet(pin.Pin.Address);
marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.pin));
NativeMap.AddMarker(marker);
}
isDrawn = true;
}
}
}
}
更多详情Click here