我不知道尝试这样做是否真实,但我试图通过设计InfoWindow(在Android的情况下)或标注来自定义我的Xamarin Forms地图(在iOS的情况下)使用Xamarin Forms。
我在Android中的自定义渲染器如下:
type GeographicMapRenderer() =
inherit MapRenderer()
let mutable formsMap = Unchecked.defaultof<DashboardMap>
let mutable googleMap = Unchecked.defaultof<GoogleMap>
let markerViewModel = new Dictionary<string, MarkerViewModel>()
let subscriptions = new CompositeDisposable()
let infoWindowClicked _ eventArgs = eventArgs |> ignore
let infoWindowEventHandler = new EventHandler<Android.Gms.Maps.GoogleMap.InfoWindowClickEventArgs>(infoWindowClicked)
override this.OnElementChanged e =
base.OnElementChanged(e)
match box e.OldElement with
| null -> e |> ignore
| _ -> googleMap.InfoWindowClick.RemoveHandler infoWindowEventHandler
match box e.NewElement with
| null -> e |> ignore
| _ -> formsMap <- e.NewElement :?> DashboardMap; base.Control.GetMapAsync(this)
override __.Dispose(disposing) = if disposing then subscriptions.Clear()
interface IOnMapReadyCallback with
member this.OnMapReady map =
googleMap <- map
let pinsUpdated _ =
googleMap.Clear()
markerViewModel.Clear()
for pin in formsMap.PinnedLocations do
let marker = new MarkerOptions()
match pin.ViewModel.Details with
| SearchResult _ -> marker.SetIcon(BitmapDescriptorFactory.DefaultMarker(BitmapDescriptorFactory.HueRed)) |> ignore
| PlaceOfInterest _ -> marker.SetIcon(BitmapDescriptorFactory.DefaultMarker(BitmapDescriptorFactory.HueAzure)) |> ignore
marker.SetPosition(new LatLng(pin.Location.Latitude / 1.0<deg>, pin.Location.Longitude / 1.0<deg>)) |> ignore
googleMap.AddMarker marker |> fun m -> markerViewModel.[m.Id] <- pin.ViewModel
formsMap.PinnedLocations.ItemsAdded.ObserveOn(RxApp.MainThreadScheduler).Subscribe(pinsUpdated) |> subscriptions.Add
formsMap.PinnedLocations.ItemsRemoved.ObserveOn(RxApp.MainThreadScheduler).Subscribe(pinsUpdated) |> subscriptions.Add
googleMap.InfoWindowClick.AddHandler infoWindowEventHandler
googleMap.SetInfoWindowAdapter this
interface Android.Gms.Maps.GoogleMap.IInfoWindowAdapter with
member __.GetInfoContents(marker: Marker): Android.Views.View = Unchecked.defaultof<Android.Views.View>
member __.GetInfoWindow(marker: Marker): Android.Views.View =
let view = markerViewModel.[marker.Id] |> ViewLocator.Current.ResolveView :?> Xamarin.Forms.VisualElement
view.Parent <- formsMap
let renderer = Platform.CreateRenderer(view)
renderer.Tracker.UpdateLayout()
let vg = renderer.ViewGroup
vg :> Android.Views.View
interface IJavaObject with member __.Handle = base.Handle
interface IDisposable with member __.Dispose() = base.Dispose()
请注意GetInfoWindow
方法中发生的情况。 ViewLocator
找到包含应在InfoWindow中显示的内容的Xamarin Forms视图。这必须转换为Android视图,为此我使用Platform.GetRenderer()
。这给出了默认的渲染器,它应该渲染视图的子项。
不幸的是,回来的Android视图没有子元素:它只是一个大的蓝色面板。
我是否需要为InfoWindow编写自定义渲染器,还是我还缺少另一个关键步骤?