Xamarin.Forms.Maps 如何像谷歌地图一样在图钉旁边/上方有一个标签?

Posted

技术标签:

【中文标题】Xamarin.Forms.Maps 如何像谷歌地图一样在图钉旁边/上方有一个标签?【英文标题】:Xamarin.Forms.Maps how to have a label next to / above pin just like Google Maps? 【发布时间】:2021-11-20 23:35:42 【问题描述】:

我想知道当您放大时是否可以在 Xamarin.Forms.Maps 中的图钉上方或旁边显示标签,并且该地点的名称显示在图钉旁边,如下所示:

谷歌地图

ios

非常感谢!

【问题讨论】:

【参考方案1】:

我们可以在每个平台上使用自定义渲染器来做到这一点。

这里是一个iOS解决方案的例子,只需添加一个子视图并在GetViewForAnnotation 方法中调整它的位置。

[assembly:ExportRenderer(typeof(CustomMap),typeof(CustomMapRenderer))]
namespace My_Forms_Test3.iOS

    public 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 -= OnCallourAccessoryControlTapped;
                nativeMap.DidSelectAnnotationView -= OnDidSelect;
                nativeMap.DidDeselectAnnotationView -= OnDidDeSelect;
            
            if (e.NewElement != null)
            
                var formsMap = (CustomMap)e.NewElement;
                var nativeMap = Control as MKMapView;
                customPins = formsMap.CustomPins;
                nativeMap.GetViewForAnnotation = GetViewForAnnotation;
                nativeMap.CalloutAccessoryControlTapped += OnCallourAccessoryControlTapped;
                nativeMap.DidSelectAnnotationView += OnDidSelect;
                nativeMap.DidDeselectAnnotationView += OnDidDeSelect;

            

        

        private void OnDidDeSelect(object sender, MKAnnotationViewEventArgs e)
        
            if (!e.View.Selected)
            
                customPinView.RemoveFromSuperview();
                customPinView.Dispose();
                customPinView = null;

            
           

        

        private void OnDidSelect(object sender, MKAnnotationViewEventArgs e)
        

            throw new NotImplementedException();
        

        private void OnCallourAccessoryControlTapped(object sender, MKMapViewAccessoryTappedEventArgs e)
        
            throw new NotImplementedException();
        

        protected override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
        
         
            MKAnnotationView annotationView = null;
        
            if (annotation is MKUserLocation)
                return null;
            var customPin = GetCustomPin(annotation as MKPointAnnotation);
            if (customPin == null)
            
                throw new Exception("not found");
            
            annotationView = mapView.DequeueReusableAnnotation(customPin.Name);
            if (annotationView == null)
            
                annotationView = new CustomMKAnnotationView(annotation, customPin.Name);
                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).Name = customPin.Name;
                customPinView = new UIView();
                var Label = new UILabel();
                Label.Text = "Samsung";
                Label.Frame=new CGRect(annotationView.GetFrame().X+35,annotationView.GetFrame().Y,100,50);
                var Label2 = new UILabel();
                Label2.Text = "20:20";
                Label2.Frame = new CGRect(annotationView.GetFrame().X + 35, annotationView.GetFrame().Y+20, 100, 50);
                customPinView.Frame= new CGRect(annotationView.GetFrame().X+40, annotationView.GetFrame().Y-20, 100, 50);
                customPinView.AddSubview(Label);
                customPinView.AddSubview(Label2);
                Label.BaselineAdjustment = UIBaselineAdjustment.AlignBaselines;
                customPinView.BackgroundColor = UIColor.White;
                customPinView.Layer.CornerRadius = 5;
                customPinView.Alpha = (nfloat)0.8;
                customPinView.Layer.MasksToBounds = true;
                annotationView.AddSubview(customPinView);
            
            annotationView.CanShowCallout = true;
         
            return annotationView;

        

        CustomPin GetCustomPin(MKPointAnnotation annotation)
        
            var position = new Position(annotation.Coordinate.Latitude, annotation.Coordinate.Longitude);
            foreach (var pin in customPins)
            
                if (pin.Position == position)
                 return pin; 
            
            return null;

        

请参阅https://***.com/a/69265658/8187800。

【讨论】:

Cole 你一直在帮助我解决我所有的 Xamarin.Forms 问题已经有一段时间了,你是最棒的,非常感谢,我会尽快尝试并将其标记为答案. 嗨@Jimmy,问题解决了吗? 我没有机会尝试,但我会在几天内尽快尝试 好的,没关系。 所以它并没有真正起作用,我得到了该位置旁边的白色矩形而不是文本,并且我无法使背景透明,是否有自定义渲染器功能让它看起来像官方应用?

以上是关于Xamarin.Forms.Maps 如何像谷歌地图一样在图钉旁边/上方有一个标签?的主要内容,如果未能解决你的问题,请参考以下文章

在运行时使用 Xamarin.Forms.Maps 创建折线时如何附加位置?

如何在单击 xamarin.forms.maps iOS c# 时更改 pin 图标

从 ViewModel 绑定到 Xamarin.Forms.Maps.Map

在 iOS 上的 Xamarin.Forms.Maps 中使用 Xamarin.Essentials Geolocation 获取设备位置的奇怪问题

有没有办法在 iOS 项目上禁用 xamarin.forms.maps 上的信息窗口?

有没有办法动画Xamarin.Forms.Maps针运动