Xamarin Forms CustomMapRenderer iOS
问题描述:
目前正致力于让自定义引脚在Android和iOS上的地图上工作,但它目前正在Android上工作,我在下面的代码中正在经历一个null异常(完全自定义渲染器) iOS上的自定义渲染器,我正在努力弄清楚是什么导致它。Xamarin Forms CustomMapRenderer iOS
CustomPin GetCustomPin(MKPointAnnotation annotation)
{
var position = new Position(annotation.Coordinate.Latitude, annotation.Coordinate.Longitude);
foreach (var pin in customPins)
{
if (pin.Pin.Position == position)
{
return pin;
}
}
return null;
}
我已经从在https://developer.xamarin.com/guides/xamarin-forms/application-fundamentals/custom-renderer/map/customized-pin/提供的Xamarin样本复制的代码和样品正确应用定制销。
我custommaprenderer:
[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace WorkingWithMaps.iOS
{
class CustomMapRenderer : MapRenderer
{
UIView customPinView;
List<CustomPin> customPins;
protected override void OnElementChanged(ElementChangedEventArgs<View> e)
{
base.OnElementChanged(e);
if (e.OldElement != null)
{
var nativeMap = Control as MKMapView;
nativeMap.GetViewForAnnotation = null;
nativeMap.CalloutAccessoryControlTapped -= OnCalloutAccessoryControlTapped;
nativeMap.DidSelectAnnotationView -= OnDidSelectAnnotationView;
nativeMap.DidDeselectAnnotationView -= OnDidDeselectAnnotationView;
}
if (e.NewElement != null)
{
var formsMap = (CustomMap)e.NewElement;
var nativeMap = Control as MKMapView;
customPins = formsMap.CustomPins;
nativeMap.GetViewForAnnotation = GetViewForAnnotation;
nativeMap.CalloutAccessoryControlTapped += OnCalloutAccessoryControlTapped;
nativeMap.DidSelectAnnotationView += OnDidSelectAnnotationView;
nativeMap.DidDeselectAnnotationView += OnDidDeselectAnnotationView;
}
}
MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
{
MKAnnotationView annotationView = null;
if (annotation is MKUserLocation)
return null;
var anno = annotation as MKPointAnnotation;
var customPin = GetCustomPin(anno);
if (customPin == null)
{
throw new Exception("Custom pin not found");
}
annotationView = mapView.DequeueReusableAnnotation(customPin.Id);
if (annotationView == null)
{
annotationView = new CustomMKAnnotationView(annotation, customPin.Id);
annotationView.Image = UIImage.FromFile("pin.png");
annotationView.CalloutOffset = new CGPoint(0, 0);
annotationView.LeftCalloutAccessoryView = new UIImageView(UIImage.FromFile("monkey.png"));
annotationView.RightCalloutAccessoryView = UIButton.FromType(UIButtonType.DetailDisclosure);
((CustomMKAnnotationView)annotationView).Id = customPin.Id;
((CustomMKAnnotationView)annotationView).Url = customPin.Url;
}
annotationView.CanShowCallout = true;
return annotationView;
}
void OnCalloutAccessoryControlTapped(object sender, MKMapViewAccessoryTappedEventArgs e)
{
var customView = e.View as CustomMKAnnotationView;
if (!string.IsNullOrWhiteSpace(customView.Url))
{
UIApplication.SharedApplication.OpenUrl(new Foundation.NSUrl(customView.Url));
}
}
void OnDidSelectAnnotationView(object sender, MKAnnotationViewEventArgs e)
{
var customView = e.View as CustomMKAnnotationView;
customPinView = new UIView();
if (customView.Id == "Xamarin")
{
customPinView.Frame = new CGRect(0, 0, 200, 84);
var image = new UIImageView(new CGRect(0, 0, 200, 84));
image.Image = UIImage.FromFile("xamarin.png");
customPinView.AddSubview(image);
customPinView.Center = new CGPoint(0, -(e.View.Frame.Height + 75));
e.View.AddSubview(customPinView);
}
}
void OnDidDeselectAnnotationView(object sender, MKAnnotationViewEventArgs e)
{
if (!e.View.Selected)
{
customPinView.RemoveFromSuperview();
customPinView.Dispose();
customPinView = null;
}
}
CustomPin GetCustomPin(MKPointAnnotation annotation)
{
var position = new Position(annotation.Coordinate.Latitude, annotation.Coordinate.Longitude);
foreach (var pin in customPins)
{
if (pin.Pin.Position == position)
{
return pin;
}
}
return null;
}
}
}
答
您设定的PIN缺少这里需要ID:
annotationView = mapView.DequeueReusableAnnotation(customPin.Id);
*:
var pin = new CustomPin
{
Id="Xamarin",
Pin = new Pin
{
Type = PinType.Place,
Position = new Position(55.240121, 10.469895),
Label = "Testing Pins"
}
};
也代替
if (annotation is MKUserLocation)
return null;
var anno = annotation as MKPointAnnotation;
使用
var anno = annotation as MKPointAnnotation;
if (anno == null)
return null;
因为注释可以是别的东西,你可以看到下面。
此外,我发现下面的代码(在此事件处理程序中使用MoveToRegion)会为此渲染器创建问题,因为GetViewForAnnotation开始接收除MKPointAnnotation之外的参数,但上面的投射保护可防止它崩溃。下面的代码的另一个问题是,如果您的销钉位置远离您的真实位置,您将看不到定制销钉和定位器跟踪器将始终将您的地图放入您的位置。在这种情况下调试您的引脚位置只需注释掉“移动”行如下。
maplocator.PositionChanged += (sender, e) =>
{
var position = e.Position;
//map.MoveToRegion(MapSpan.FromCenterAndRadius(new Position(position.Latitude, position.Longitude), Distance.FromKilometers(2)));
};
函数OnReverseGeocodeButtonClicked将很快崩溃:-),因为您的类成员引脚未分配。
warning CS0649: Field 'MainPage.pin' is never assigned to, and will always have its default value null
非常抱歉,错误的代码!当我发布这个问题时并不完全清醒,但现在已经修复了。感谢您的所有反馈。 –
即使有您的更改,我仍会在引脚进入视图时收到空引用。 –
更具体地说,它现在声称我的customPin列表为空 –