Xamarin - 自定义地图的样式

时间:2016-05-19 10:29:28

标签: xamarin maps customization xamarin.forms

我的公司问我是否可以在某些方面设计地图,但是,我认为不可能,但我不确定。

SnazzyMaps is the example taken by company

要求的自定义设置是:背景颜色,道路颜色,弹出窗口时的白色滤镜,类似的东西!我已经拥有自定义路径,自定义引脚的CustomMap广告,但这还不够。

谢谢!

1 个答案:

答案 0 :(得分:1)

我从我的应用程序中为您提供自定义渲染器类(使用来自nuget的Xamarin表单映射)

for iOS

  

`using System;
using System.Collections.Generic;
using CoreGraphics;
using CustomRenderer;
using CustomRenderer.iOS;
using MapKit;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.iOS;
using Xamarin.Forms.Platform.iOS;
using App;
using CoreLocation;
using App.iOS;
using Foundation;

[assembly:ExportRenderer (typeof(CustomMap), typeof(CustomMapRenderer))]
namespace App.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.DidSelectAnnotationView -= OnDidSelectAnnotationView;
                nativeMap.DidDeselectAnnotationView -= OnDidDeselectAnnotationView;
            }

            if (e.NewElement != null) {
                var formsMap = (CustomMap)e.NewElement;
                var nativeMap = Control as MKMapView;
                nativeMap.MapType = MKMapType.Standard;
                customPins = formsMap.CustomPins;

                nativeMap.GetViewForAnnotation = GetViewForAnnotation;
                nativeMap.DidSelectAnnotationView += OnDidSelectAnnotationView;
                nativeMap.DidDeselectAnnotationView += OnDidDeselectAnnotationView;
                nativeMap.CalloutAccessoryControlTapped += OnCalloutAccessoryControlTapped;
            }
        }

        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 ("Identifier");
            if (annotationView == null) {
                annotationView = new CustomMKAnnotationView (annotation, customPin.Pin.Label);
                annotationView.Image = UIImage.FromFile ("pizzastueck.png");
                annotationView.CalloutOffset = new CGPoint (0, 0);
                annotationView.RightCalloutAccessoryView = annotationView.RightCalloutAccessoryView = UIButton.FromType (UIButtonType.DetailDisclosure);;
                ((CustomMKAnnotationView)annotationView).HLabel = customPin.Pin.Label;
                ((CustomMKAnnotationView)annotationView).SLabel = customPin.Pin.Address;
                ((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)) {
                var url = customView.Url+"/app/auswahl-speisen.php";
                ((CustomMap)Element).OnTap(url.ToString());
//              var t = (UIView)this;
//              var webView = new UIWebView();      
//              webView.Frame = new CGRect(0,0,t.Frame.Size.Width,t.Frame.Size.Height);
//
//              webView.LoadRequest (new NSUrlRequest (new NSUrl (url)));
//              webView.ScalesPageToFit = true;
//              webView.LoadError += (object sender1, UIWebErrorArgs e1) => { Console.WriteLine(e1.Error.LocalizedDescription); };
//              t.AddSubview(webView);
            }

        }

        void OnDidSelectAnnotationView (object sender, MKAnnotationViewEventArgs e)
        {

            var customView = e.View as CustomMKAnnotationView;
            customPinView = new UIView ();
                customPinView.Frame = new CGRect (0, 0, 200, 200);
                var image = new UIImageView (new CGRect (0, 0, 220, 200));
//          var HeadingLabel = new UILabel () {Text = customView.HLabel, Frame = new CGRect (0, image.Frame.Size.Height / 2, 200, 30)
//          };
//          var SubsTitleLabel = new UILabel () {Text = customView.SLabel, Frame = new CGRect (0, HeadingLabel.Frame.Y+HeadingLabel.Frame.Size.Height, 200, 30)
//          };
//          var my = new UITapGestureRecognizer(tapped);
//          customPinView.AddGestureRecognizer (my);
//          customView.BringSubviewToFront (customPinView);
            image.Image = UIImage.FromFile ("Maps_InfoBOX.png");
                customPinView.AddSubview (image);
//              customPinView.AddSubview (HeadingLabel);
//              customPinView.AddSubview (SubsTitleLabel);
                customPinView.Center = new CGPoint (0, -(e.View.Frame.Height+50  ));
                customView.AddSubview (customPinView);

            var mapview = (MKMapView)sender;
            var t = e.View.Annotation;
            var m = t.Coordinate;
            var Coordinate = new CLLocationCoordinate2D (m.Latitude, m.Longitude);
            mapview.SetCenterCoordinate (Coordinate, true);

        }
//      public void tapped(UITapGestureRecognizer tap) {
//          
//      }
        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;
        }
    }
}

`

对于android

using System;
using System.Collections.Generic;
using System.ComponentModel;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Widget;
using CustomRenderer;
using CustomRenderer.Droid;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using App;
using App.Droid;
using Android.Webkit;
using Android.Views;
using Android.App;


[assembly:ExportRenderer (typeof(CustomMap), typeof(CustomMapRenderer))]
namespace CustomRenderer.Droid
{
    public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter, IOnMapReadyCallback
    {
        GoogleMap map;
        List<CustomPin> customPins;
        bool isDrawn;
        Android.Webkit.WebView myWebView;

        protected override void OnElementChanged (Xamarin.Forms.Platform.Android.ElementChangedEventArgs<Xamarin.Forms.View> e)
        {
            base.OnElementChanged (e);

            if (e.OldElement != null) {
                map.InfoWindowClick -= OnInfoWindowClick;
            }

            if (e.NewElement != null) {
                var formsMap = (CustomMap)e.NewElement;
                customPins = formsMap.CustomPins;
                ((MapView)Control).GetMapAsync (this);
            }
        }

        public void OnMapReady (GoogleMap googleMap)
        {
            map = googleMap;
            map.InfoWindowClick += OnInfoWindowClick;
            map.SetInfoWindowAdapter (this);
        }

        protected override void OnElementPropertyChanged (object sender, PropertyChangedEventArgs e)
        {
            base.OnElementPropertyChanged (sender, e);

            if (e.PropertyName.Equals ("VisibleRegion") && !isDrawn) {
                map.Clear ();
                if (customPins != null) {
                    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.pizzastueck2));

                        map.AddMarker (marker);
                    }
                }
                isDrawn = true;
            }
        }

        protected override void OnLayout (bool changed, int l, int t, int r, int b)
        {
            base.OnLayout (changed, l, t, r, b);

            if (changed) {
                isDrawn = false;
            }
        }

        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+"/app/auswahl-speisen.php");

                ((CustomMap)Element).OnTap(url.ToString());

                }
            }

        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");
                }

                    view = inflater.Inflate (Resource.Layout.XamarinMapInfoWindow, 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.Pin.Position == position) {
                    return pin;
                }
            }
            return null;
        }
        public override bool OnKeyDown (Android.Views.Keycode keyCode, Android.Views.KeyEvent e)
        {
            if (keyCode == Keycode.Back && myWebView.CanGoBack ()) {
                myWebView.GoBack ();
                return true;
            }

            return base.OnKeyDown (keyCode, e);
        }
    }
    class MyWebClient :WebViewClient
    {
        public override bool ShouldOverrideUrlLoading (Android.Webkit.WebView view, string url)
        {
            view.LoadUrl (url);
            return true;
        }

    }
}

在共享项目中

using System.Collections.Generic;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using System;

namespace App
{
    public class MapPage : ContentPage
    {
        public  CustomMap customMap1{ get; set;}
        public MapPage ()
        {
            Title ="Stores";
            Icon = "flag_map_marker4.png";


             var customMap = new CustomMap {
                MapType = MapType.Street,
                WidthRequest = App.ScreenWidth,
                HeightRequest = App.ScreenHeight
            };

            customMap.CustomPins = new List<CustomPin>();
            if (App.Items != null && App.Items.Count > 0) {
                foreach (var t in App.Items) {
                    var temp = new CustomPin () {
                        Pin = new Pin () {
                            Label = t.Name,
                            Type = PinType.Place,
                            Position = new Position (t.Lat, t.Lon),
                            Address = t.Address1
                        },
                        Url = t.Link
                    };
                    customMap.CustomPins.Add (temp);
                }
                foreach (var pin in customMap.CustomPins) {
                    customMap.Pins.Add (pin.Pin);
                }
                // dont delete below code ,they will save you if timer doesnt work .

                //var temp1 = new MapSpan(customMap.CustomPins [0].Pin.Position,
//              if(Device.OS == TargetPlatform.iOS)
//              customMap.MoveToRegion (MapSpan.FromCenterAndRadius (customMap.CustomPins [0].Pin.Position, Distance.FromMiles (0.20)));

                if(Device.OS == TargetPlatform.Android)
                customMap.MoveToRegion (MapSpan.FromCenterAndRadius (customMap.CustomPins [0].Pin.Position, Distance.FromMiles (55.0)));
                if (Device.OS == TargetPlatform.iOS) {
                    Device.StartTimer (TimeSpan.FromMilliseconds (500), () => {
                        customMap.MoveToRegion (MapSpan.FromCenterAndRadius (customMap.CustomPins [0].Pin.Position, Distance.FromMiles (55.0)));
                        return false;
                    });
                }
            }

            Content = customMap;
        }

    }


}

这么多代码会为你提供足够的想法