Xamarin Forms - 自定义地图标记不可见
Xamarin Forms - custom map marker not visible
我正在关注 MS 页面上关于 Custom map renderer 的文章,但我无法让它在 android 上工作。地图显示但图钉(标记)不存在。我没有发现我所做的与官方文档有什么不同(如前link)。当我调试时,customPins 集合中有 3 个标记。自定义渲染器适用于 UWP。所以问题仅在 Android 代码中。
这是我的 Android 的 CustomRender 代码,它不显示引脚。
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;
}
}
}
有人知道为什么这行不通吗?
注意:由于出现错误,我不得不修改官方MS代码。无论 Android.Views.View
在哪里,我都必须将其修改为 global::Android.Views.View
否则会出现以下错误
"'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'.".
和
The type or namespace name 'Views' does not exist in the namespace
'iVanApp.Android' (are you missing an assembly reference?)
希望这没有破坏我的代码。
在调查和阅读其他人的自定义地图问题(以及主要解决方案)后,我得到了一个变通解决方案如何在地图上获取图钉,但在我单击图钉(标记)时不显示信息 window。 。如果我修改 OnMapReday 并调用和添加方法 SetMapMarkers,则引脚可见,但正如我所说,当我单击引脚
时,不会显示任何信息 window
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));
}
}
虽然这是解决方案,但我更愿意在没有此解决方法的情况下让它工作。因此,我并没有付出太多努力,为什么点击 pin 时没有显示信息 window。如果没有这个变通办法就没有解决方案,那么我会对有变通办法的解决方案感兴趣,但正如我所说,我不喜欢这样做。
正如 FreakyAli 所说,为 CustomMap 添加自定义图钉和位置。
<local:CustomMap x:Name="customMap" MapType="Street" />
添加自定义图钉并使用 MoveToRegion 方法定位地图视图
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)));
}
我可以通过点击地图图钉来获取信息窗口,没问题。
我正在关注 MS 页面上关于 Custom map renderer 的文章,但我无法让它在 android 上工作。地图显示但图钉(标记)不存在。我没有发现我所做的与官方文档有什么不同(如前link)。当我调试时,customPins 集合中有 3 个标记。自定义渲染器适用于 UWP。所以问题仅在 Android 代码中。
这是我的 Android 的 CustomRender 代码,它不显示引脚。
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;
}
}
}
有人知道为什么这行不通吗?
注意:由于出现错误,我不得不修改官方MS代码。无论 Android.Views.View
在哪里,我都必须将其修改为 global::Android.Views.View
否则会出现以下错误
"'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'.".
和
The type or namespace name 'Views' does not exist in the namespace 'iVanApp.Android' (are you missing an assembly reference?)
希望这没有破坏我的代码。
在调查和阅读其他人的自定义地图问题(以及主要解决方案)后,我得到了一个变通解决方案如何在地图上获取图钉,但在我单击图钉(标记)时不显示信息 window。
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));
}
}
虽然这是解决方案,但我更愿意在没有此解决方法的情况下让它工作。因此,我并没有付出太多努力,为什么点击 pin 时没有显示信息 window。如果没有这个变通办法就没有解决方案,那么我会对有变通办法的解决方案感兴趣,但正如我所说,我不喜欢这样做。
正如 FreakyAli 所说,为 CustomMap 添加自定义图钉和位置。
<local:CustomMap x:Name="customMap" MapType="Street" />
添加自定义图钉并使用 MoveToRegion 方法定位地图视图
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)));
}
我可以通过点击地图图钉来获取信息窗口,没问题。