Xamarin Forms Maps 自定义 Android 渲染器 GetMapAsync 不调用 OnMapReady [英] Xamarin Forms Maps Custom Android Renderer GetMapAsync Not Calling OnMapReady

查看:46
本文介绍了Xamarin Forms Maps 自定义 Android 渲染器 GetMapAsync 不调用 OnMapReady的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了 GetMapAsync 的问题 没有调用 OnMapReady 我可以通过检查地图是否为空来抑制错误,然后地图将使用非自定义标记加载.如果我然后稍微移动地图 OnMapReady 将加载,然后将显示自定义标记.以下是我的自定义渲染器类,如果其他人遇到此问题,我将非常感谢您的解决方案.

I am running into an issue with GetMapAsync Not calling OnMapReady I am able to suppress the error by checking if the map is null the map will then load with non custom markers. If I then move the map slightly OnMapReady will load and the custom markers will then be displayed. Below is my custom renderer class, if anyone else has ran into this issue I would be very grateful to hear your resolution.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using Android.Content;
using Android.Gms.Maps;
using Android.Gms.Maps.Model;
using Android.Views;
using Android.Widget;
using BSi.Mobile.Events.Controls;
using BSi.Mobile.Events.Droid.Renderers;
using BSi.Mobile.Events.Events;
using Xamarin.Forms;
using Xamarin.Forms.Maps;
using Xamarin.Forms.Maps.Android;
using View = Xamarin.Forms.View;

[assembly: ExportRenderer(typeof(CustomMap), typeof(CustomMapRenderer))]
namespace BSi.Mobile.Events.Droid.Renderers
{
    public class CustomMapRenderer : MapRenderer, GoogleMap.IInfoWindowAdapter, IOnMapReadyCallback
    {
        GoogleMap map;
        IList<CustomPin> customPins;
        private CustomPin selectedPin;
        bool isDrawn;

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

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

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

        public void OnMapReady(GoogleMap googleMap)
        {
            map = googleMap;
            map.InfoWindowClick += OnInfoWindowClick;
            map.MarkerClick += OnMarkerClick;
            map.MapClick += OnMapClick;
            map.SetInfoWindowAdapter(this);
            SetMapMarkers();
        }

        private void SetMapMarkers()
        {
            map.Clear();

            foreach (var pin in customPins)
            {
                addMarker(pin, false);
            }
            isDrawn = true;
            if (selectedPin != null)
            {
                addMarker(selectedPin, true);
            }
        }

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

            if (e.PropertyName.Equals("VisibleRegion") && !isDrawn && map != null)
            {
                SetMapMarkers();
            }
            else if (e.PropertyName.EndsWith("SelectedPin") && map != null)
            {
                var customMap = sender as CustomMap;
                selectedPin = customMap?.SelectedPin;
                if (selectedPin != null)
                {
                    addMarker(selectedPin, true);
                }
            }
        }

        private void addMarker(CustomPin pin, bool isSelected)
        {
            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);
            switch (pin.Id)
            {
                case "Convention":
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.star));
                    break;
                case "cafe":
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.cafe));
                    break;
                case "bar":
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.bar));
                    break;
                default:
                    marker.SetIcon(BitmapDescriptorFactory.FromResource(Resource.Drawable.restaurant));
                    break;
            }

            var selectedMarker = map.AddMarker(marker);

            if (isSelected)
                selectedMarker.ShowInfoWindow();
        }

        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            //Catches Exception incase user needs to update google play services
            try
            {
                base.OnLayout(changed, l, t, r, b);

                if (changed)
                {
                    isDrawn = false;
                }
            }
            catch (Exception ex)
            {
               Console.WriteLine(ex.ToString());
            }  
        }

        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);
                var intent = new Intent(Intent.ActionView, url);
                intent.AddFlags(ActivityFlags.NewTask);
                Android.App.Application.Context.StartActivity(intent);
            }
        }

        public Android.Views.View GetInfoContents(Marker marker)
        {
            var inflater = Android.App.Application.Context.GetSystemService(Context.LayoutInflaterService) as LayoutInflater;
            if (inflater != null)
            {
                Android.Views.View view;

                var customPin = GetCustomPin(marker);
                if (customPin == null)
                {
                    throw new Exception("Custom pin not found");
                }

                switch (customPin.Id)
                {
                    case "Conference":
                        view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);
                        break;
                    default:
                        view = inflater.Inflate(Resource.Layout.MapInfoWindow, null);
                        break;
                }

                var infoTitle = view.FindViewById<TextView>(Resource.Id.InfoWindowTitle);
                var infoSubtitle = view.FindViewById<TextView>(Resource.Id.InfoWindowSubtitle);
                var infoPhone = view.FindViewById<TextView>(Resource.Id.InfoWindowPhone);
                var infoWebsite = view.FindViewById<TextView>(Resource.Id.InfoWindowWebsite);

                if (infoTitle != null)
                {
                    infoTitle.Text = marker.Title;
                }
                else
                {
                    infoTitle.Visibility = ViewStates.Gone;
                }

                if (infoSubtitle != null)
                {
                    infoSubtitle.Text = marker.Snippet;
                }
                else
                {
                    infoSubtitle.Visibility = ViewStates.Gone;

                }

                if (infoPhone != null && customPin.Phone != null)
                {
                    infoPhone.Text = customPin.Phone;
                }
                else
                {
                    infoPhone.Visibility = ViewStates.Gone;
                }

                if (infoWebsite != null && customPin.Url != null)
                {
                    infoWebsite.Text = customPin.Url;
                }
                else
                {
                    infoWebsite.Visibility = ViewStates.Gone;
                }

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

        private void OnMarkerClick(object sender, GoogleMap.MarkerClickEventArgs e)
        {
            e.Handled = false;
            App.EventAggregator?.GetEvent<MapClickedEvent>().Publish(new Pin { Position = new Position(e.Marker.Position.Latitude, e.Marker.Position.Longitude), Label = e.Marker.Title});
        }

        private void OnMapClick(object sender, GoogleMap.MapClickEventArgs e)
        {
            App.EventAggregator?.GetEvent<MapClickedEvent>().Publish(null);
        }
    }
}

推荐答案

我找到了解决此问题的变通方法 我移动了代码,在它自己的函数中设置地图标记,从那里我在 OnElementPropertyChanged 中调用该函数作为与正常执行.这会在地图移动时设置标记.为了在地图加载时加载自定义标记,我还在 onMapReady 中调用了设置标记.我上面的代码现在反映了一个有效的解决方案,我希望我已经帮助了其他可能遇到这个问题的人干杯!

I found a work around to fix this issue I moved the code where I setup the map markers inside its own function, from there I call that function inside OnElementPropertyChanged as with the normal execution. This sets up the markers when the map moves. To load the custom markers when the map loads I also called setup markers inside onMapReady. My Code Above now reflects a working solution, I hope I have helped anyone else out who may run into this issue Cheers!

这篇关于Xamarin Forms Maps 自定义 Android 渲染器 GetMapAsync 不调用 OnMapReady的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆