Xamarin表单:自定义InfoWindow

时间:2017-01-29 01:39:45

标签: android f# xamarin.forms

我不知道尝试这样做是否真实,但我试图通过设计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编写自定义渲染器,还是我还缺少另一个关键步骤?

0 个答案:

没有答案