我有一个 Xamarin Forms 地图应用程序,我正在使用适用于 Android 的此文档的自定义地图渲染器。 我成功地构建了一个引脚。 现在我想制作几个引脚,因此为了减少代码的重复性,我将我的数据(示例数据)添加到 Mydata.json 文件中并使其从中读取。然而,只有一个引脚数据有效,并且在许多情况下,应用程序仅考虑最后一个引脚数据。 这是 data.json:
[
{"Label" :"Country1",
"Address":"A multine paragraph",
"Lat":"-12",
"Lng":"14",
"Name":"Tamarin",
"Url": "http://xamarin.com/about/"
},
{ "Label" :"Country2",
"Address":"Multiline paragraph",
"Lat":"-25",
"Lng":"45",
"Name":"Camarin",
"Url": "http://xamarin.com/about/"
},
{ "Label" :"Country3",
"Address":"Multiline paragraphMultiline paragraphMultiline paragraphMultiline paragraphMultiline paragraphMultiline paragraphMultiline paragraphMultiline paragraph",
"Lat":"-5",
"Lng":"45",
"Name":"Xamarin",
"Url": "http://xamarin.com/about/"
}
]
这是我的 CustomMapRenderer:
using System;
using System.Collections.Generic;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using Orbage;
using Orbage.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace Orbage.Droid
{
public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter
{
List<CustomPin> customPins;
public CustomMapRenderer(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 = (CustomMap)e.NewElement;
customPins = formsMap.CustomPins;
}
}
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.Url))
{
var url = Android.Net.Uri.Parse(customPin.Url);
var intent = new Intent(Intent.ActionView, url);
intent.AddFlags(ActivityFlags.NewTask);
Android.App.Application.Context.StartActivity(intent);
}
}
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");
}
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 Android.Views.View GetInfoWindow(Marker marker)
{
return null;
}
CustomPin 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;
}
}
}
我设置密码的位置:
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms.Maps;
namespace Orbage
{
public class CustomPin : Pin
{
public string Name { get; set; }
public string Url { get; set; }
}
}
其余代码只是 Microsoft 文档的逐步改编,但是,如果我误判了分析问题所需的代码量,请告诉我。
如您所见,从第 82 行开始,第二个异常结果为 true;即自定义引脚为空;但该引脚存在于数据文件中,并且由于某种原因无法读取它,我无法找出原因。我相信这与对象引用有关,但我找不到问题所在。 对于任何明显的原因(如果有的话),我提前表示歉意;因为我对此不太熟悉 谢谢。
感谢@Jason 的评论,以及来自here的这篇文章,我找到了问题所在。
customMap.CustomPins = new List<CustomPin> { pin };
这是我的 MapPage.xaml.cs 中的 foreach 内部:
foreach (var place in places)
{
CustomPin pin = new CustomPin
{
Type = PinType.Place,
Position = new Position(Double.Parse(place.Lat), Double.Parse(place.Lng)),
Label = place.Label,
Address = place.Address,
Name = place.Name,
Url = place.Url
};
customMap.CustomPins = new List<CustomPin> { pin }; //This one
customMap.Pins.Add(pin);
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.79752, -122.40183), Distance.FromMiles(1.0)));
通过将其放在外面,它可以调用每个引脚。
List<CustomPin> custompinList = new List<CustomPin>(); //Outside the foreach now
foreach (var place in places)
{
CustomPin pin = new CustomPin
{
Type = PinType.Place,
Position = new Position(Double.Parse(place.Lat), Double.Parse(place.Lng)),
Label = place.Label,
Address = place.Address,
Name = place.Name,
Url = place.Url
};
custompinList.Add(pin);
customMap.Pins.Add(pin);
customMap.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(37.79752, -122.40183), Distance.FromMiles(1.0)));
}
问题就解决了。