Nullreferenceexception使用Monoandroid / Xamarin绘制Map

时间:2014-10-22 22:26:33

标签: android google-maps xamarin xamarin.android

很难搞清楚为什么我的_MapFragment的MAP属性始终为null。目前,当我到达地图页面时,我总是会收到此错误。

10-17 02:29:07.335 E/mono-rt ( 1288): [ERROR] FATAL UNHANDLED EXCEPTION: 
System.NullReferenceException: Object reference not set to an instance of an object
10-17 02:29:07.335 E/mono-rt ( 1288):   at Xamarin.Forms.Platform.Android.Platform.OnLayout (Boolean changed, Int32 l, Int32 t, Int32 r, Int32 b) [0x00000] in <filename unknown>:0 
10-17 02:29:07.335 E/mono-rt ( 1288):   at Xamarin.Forms.Platform.Android.PlatformRenderer.OnLayout (Boolean changed, Int32 l, Int32 t, Int32 r, Int32 b) [0x00000] in <filename unknown>:0 
10-17 02:29:07.335 E/mono-rt ( 1288):   at Android.Views.ViewGroup.n_OnLayout_ZIIII (IntPtr jnienv, IntPtr native__this, Boolean changed, Int32 l, Int32 t, Int32 r, Int32 b) [0x00000] in <filename unknown>:0 
10-17 02:29:07.335 E/mono-rt ( 1288):   at (wrapper dynamic-method) object:99e4ae3d-31ec-4c07-9bb3-fc4b39557d47 (intptr,intptr,bool,int,int,int,int)
10-17 02:29:07.335 W/        ( 1288): _wapi_connect: error looking up socket handle 0x31

我的自定义渲染器

    public class MapContentPageRenderer: PageRenderer
    {
        Android.Views.View view;
        private MapFragment _mapFragment;

        protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
        {
            base.OnElementChanged(e);

            var page = e.NewElement as MapContentPage;
            var activity = this.Context as Activity;

            view = activity.LayoutInflater.Inflate(Resource.Layout.MapLayout, this, false);
            AddView(view);
            InitMapFragment(activity);
            ZoomToPosition(page.InitLat, page.InitLng);
        }

        protected override void OnLayout(bool changed, int l, int t, int r, int b)
        {
            base.OnLayout(changed, l, t, r, b);
            var msw = MeasureSpec.MakeMeasureSpec(r - l, MeasureSpecMode.Exactly);
            var msh = MeasureSpec.MakeMeasureSpec(b - t, MeasureSpecMode.Exactly);
            view.Measure(msw, msh);
            view.Layout(0, 0, r - l, b - t);
        }

        private void InitMapFragment(Activity activity)
        {

            _mapFragment = activity.FragmentManager.FindFragmentByTag("map") as MapFragment;
            if (_mapFragment != null) return;
            var mapOptions = new GoogleMapOptions()
                .InvokeMapType(GoogleMap.MapTypeNormal)
                .InvokeRotateGesturesEnabled(false)
                .InvokeZoomControlsEnabled(false)
                .InvokeCompassEnabled(true);

            var fragTx = activity.FragmentManager.BeginTransaction();
            _mapFragment = MapFragment.NewInstance(mapOptions);

            fragTx.Add(Resource.Id.mapWithOverlay, _mapFragment, "map");
            fragTx.Commit();
        }

private void ZoomToPosition(double lat, double lng)
    {
        var latlng = new LatLng(lat, lng);
        var cameraPosition = new CameraPosition.Builder().Target(latlng).Zoom(14.0f).Build();
        var cameraUpdate = CameraUpdateFactory.NewCameraPosition(cameraPosition);
        _mapFragment.Map.MoveCamera(cameraUpdate);
    }
}

4 个答案:

答案 0 :(得分:1)

尝试实施IGooglePlayServicesClientConnectionCallbacks,当Google Play服务准备就绪时,将调用OnConnect。

  public class LocationManager : Java.Lang.Object, IGooglePlayServicesClientConnectionCallbacks {

    public LocationManager(GoogleMap map)
    {
        _map = map;
    }


    private readonly GoogleMap _map;

    private void SetCenter()
    {
        CameraUpdate camLocation = CameraUpdateFactory.NewLatLngZoom(CurrentLatLng, Constants.DefaultZoom);

        _map.MoveCamera(camLocation);
    }

    public void OnConnected(Bundle p0)
    {
        SetCenter();
    }

}

答案 1 :(得分:0)

尝试使用静态mapfragment(在布局中定义)。问题是fragTx.Commit();是不同步的,并确定它实际提交的时间很难。

答案 2 :(得分:0)

只是扔掉另一个选择。

您可以使用Xamarin.Forms.Maps并仅使用Android渲染器 - 已经为您完成的工作。

http://developer.xamarin.com/guides/cross-platform/xamarin-forms/working-with/maps/

如果愿意,您可以编写iOS / Win自定义渲染器以使用谷歌地图。

或者只是包装/扩展Xamarin.Forms.Maps.Android.MapRenderer(我尝试过这种方法,但我确信可以做一些工作)。

或者您可能乐意将每个平台上的原生地图用作默认设置。

答案 3 :(得分:0)

此解决方案应该是您正在寻找的。

您需要一个静态属性,您可以在创建活动时设置Bundle。

   protected override void OnElementChanged(ElementChangedEventArgs<Page> e)
   {
        base.OnElementChanged(e);
        MapView oldView = (MapView)this.Control;
        MapView newView = new MapView(this.Context);
        newView.OnCreate(Bundle);
        newView.OnResume();
        this.SetNativeControl(newView);

        var map = ((MapView)this.Control).Map 

        // other map setup goes here.  Map is already set up.

        ZoomToPosition(page.InitLat, page.InitLng);
    }


    private void ZoomToPosition(double lat, double lng)
    {
        var latlng = new LatLng(lat, lng);
        var cameraPosition = new CameraPosition.Builder().Target(latlng).Zoom(14.0f).Build();
        var cameraUpdate = CameraUpdateFactory.NewCameraPosition(cameraPosition);
        ((MapView)this.Control).Map.MoveCamera(cameraUpdate);
    }