如何在xamarin表单中的自定义页面渲染器上实现mapbox?

时间:2016-05-25 19:23:02

标签: c# android xamarin xamarin.forms mapbox

我正在尝试在自定义页面渲染器上实现mapbox xamarin.android sdk,以便从xamarin表单应用程序中使用它。到目前为止,我已经能够使用文本标签创建自定义渲染器并使用它。它看起来像这样:

//image

这是我的pageRenderer类:

[assembly: ExportRenderer (typeof(MapPage), typeof(MapPageRenderer))]
namespace mapetor.Droid
{
public class MapPageRenderer : PageRenderer, TextureView.ISurfaceTextureListener
{
   global::Android.Views.View view;
   MapView map;

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

       if (e.OldElement != null || Element == null)
       {
           return;
       }
       try
       {
           // load some android xaml
           Task.Run(() =>
           {
               SetupUserInterface();
           }).ContinueWith((rslt) =>
           {
               AddView(view);
               Device.BeginInvokeOnMainThread(() => { map.OnCreate(null); });  
           });
       }
       catch (Exception ex)
       {
           System.Diagnostics.Debug.WriteLine(ex.ToString());
       }
   }

   private async void SetupUserInterface()
   {
       var activity = this.Context as Activity;
       view = activity.LayoutInflater.Inflate(Resource.Layout.mapLayout, this, false);

       Device.BeginInvokeOnMainThread(async() =>
       {
           // instanciando el mapa
           map = FindViewById<MapView>(Resource.Id.mapView);
           map.StyleUrl = Mapbox.Constants.Style.Emerald;
           var mapboxMap = await map.GetMapAsync();
           var position = new CameraPosition.Builder()
           .Target(new LatLng(41.885, -87.679))
           .Zoom(11)
           .Build();
           mapboxMap.AnimateCamera(CameraUpdateFactory.NewCameraPosition(position), 2500);
       });
   }


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

   public void OnSurfaceTextureAvailable(Android.Graphics.SurfaceTexture surface, int width, int height)
   {
       //
   }

   public bool OnSurfaceTextureDestroyed(Android.Graphics.SurfaceTexture surface)
   {
       //
       return false;
   }

   public void OnSurfaceTextureSizeChanged(Android.Graphics.SurfaceTexture surface, int width, int height)
   {
       //
   }

   public void OnSurfaceTextureUpdated(Android.Graphics.SurfaceTexture surface)
   {
       //
   }

   public Bundle savedInstanceState { get; set; }
}

}

这是我的mapLayout.xaml文件:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#fcfcfc"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center">
<TextView
    android:text="Mapbox test"
    android:textColor="#404040"
    android:textSize="60dp"
    android:gravity="center"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" />
<com.mapbox.mapboxsdk.maps.MapView xmlns:mapbox="http://schemas.android.com/apk/res-auto"
    android:id="@+id/mapView"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    mapbox:access_token="MY_ACCESS_TOKEN" />
</LinearLayout>

然而,当我运行它时,得到这个错误:

  05-25 13:56:54.287 E/mono    (16862): Unhandled Exception:
    05-25 13:56:54.287 E/mono    (16862): Android.Views.InflateException: Binary      XML file line #1: Binary XML file line #1: Error inflating class com.mapbox.mapboxsdk.maps.MapView ---> Android.Views.InflateException: Binary XML file line #1: Error inflating class com.mapbox.mapboxsdk.maps.MapView ---> Java.Lang.Reflect.InvocationTargetException: Exception of type 'Java.Lang.Reflect.InvocationTargetException' was thrown. ---> Android.Views.InflateException: Binary XML file line #1: Binary XML file line #1: Error inflating class com.mapbox.mapboxsdk.maps.widgets.UserLocationView ---> Android.Views.InflateException: Binary XML file line #1: Error inflating class com.mapbox.mapboxsdk.maps.widgets.UserLocationView ---> Java.Lang.Reflect.InvocationTargetException: Exception of type 'Java.Lang.Reflect.InvocationTargetException' was thrown. ---> Java.Lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-25 13:56:54.287 E/mono    (16862): 
05-25 13:56:54.287 E/mono    (16862):   --- End of managed exception stack trace ---
05-25 13:56:54.287 E/mono    (16862): java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
05-25 13:56:54.287 E/mono    (16862):   at android.os.Handler.<init>(Handler.java:200)
05-25 13:56:54.287 E/mono    (16862):   at android.os.Handler.<init>(Handler.java:114)
05-25 13:56:54.287 E/mono    (16862):   at android.location.LocationManager$ListenerTransport$1.<init>(LocationManager.java:227)
05-25 13:56:54.287 E/mono    (16862):   at android.location.LocationManager$ListenerTransport.<init>(LocationManager.java:227)
05-25 13:56:54.287 E/mono    (16862):   at android.location.LocationManager.wrapListener(LocationManager.java:864)
05-25 13:56:54.287 E/mono    (16862):   at android.location.LocationManager.requestLocationUpdates(LocationManager.java:877)
05-25 13:56:54.287 E/mono    (16862):   at android.location.LocationManager.requestLocationUpdates(LocationManager.java:464)
05-25 13:56:54.287 E/mono    (16862):   at com.mapzen.android.lost.internal.FusionEngine.enablePassive(FusionEngine.java:118)
05-25 13:56:54.287 E/mono    (16862):   at com.mapzen.android.lost.internal.FusionEngine.enable(FusionEngine.java:82)
05-25 13:56:54.287 E/mono    (16862):   at com.mapzen.android.lost.internal.LocationEngine.setRequest(LocationEngine.java:36)
05-25 13:56:54.287 E/mono    (16862):   at com.mapzen.android.lost.internal.FusedLocationProviderApiImpl.requestLocationUpdates(FusedLocationProviderApiImpl.java:38)
05-25 13:56:54.287 E/mono    (16862):   at com.mapbox.mapboxsdk.location.LocationServices.toggleGPS(LocationServices.java:104)
05-25 13:56:54.287 E/mono    (16862):   at com.mapbox.mapboxsdk.maps.widgets.UserLocationView.toggleGps(UserLocationView.java:378)
05-25 13:56:54.287 E/mono    (16862):   at com.mapbox.mapboxsdk.maps.widgets.UserLocationView.setEnabled(UserLocationView.java:251)
05-25 13:56:54.287 E/mono    (16862):   at com.mapbox.mapboxsdk.maps.widgets.UserLocationView.initialize(UserLocationView.java:119)
05-25 13:56:54.287 E/mono    (16862):   at com.mapbox.mapboxsdk.maps.widgets.UserLocationView.<init>(UserLocationView.java:109)
05-25 13:56:54.287 E/mono    (16862):   at java.lang.reflect.Constructor.newInstance(Native Method)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createView(LayoutInflater.java:619)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.inflate(LayoutInflater.java:374)
05-25 13:56:54.287 E/mono    (16862):   at com.mapbox.mapboxsdk.maps.MapView.initialize(MapView.java:179)
05-25 13:56:54.287 E/mono    (16862):   at com.mapbox.mapboxsdk.maps.MapView.<init>(MapView.java:158)
05-25 13:56:54.287 E/mono    (16862):   at java.lang.reflect.Constructor.newInstance(Native Method)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createView(LayoutInflater.java:619)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.rInflate(LayoutInflater.java:835)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:798)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.inflate(LayoutInflater.java:515)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.inflate(LayoutInflater.java:423)
05-25 13:56:54.287 E/mono    (16862): 
05-25 13:56:54.287 E/mono    (16862):   --- End of inner exception stack trace ---
05-25 13:56:54.287 E/mono    (16862): 
05-25 13:56:54.287 E/mono    (16862):   --- End of managed exception stack trace ---
05-25 13:56:54.287 E/mono    (16862): java.lang.reflect.InvocationTargetException
05-25 13:56:54.287 E/mono    (16862):   at java.lang.reflect.Constructor.newInstance(Native Method)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createView(LayoutInflater.java:619)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:764)
05-25 13:56:54.287 E/mono    (16862):   at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704
05-25 13:56:54.291 D/OpenGLRenderer(16862): Use EGL_SWAP_BEHAVIOR_PRESERVED: true
referenceTable GDEF length=814 1
referenceTable GSUB length=11364 1
referenceTable GPOS length=47302 1

我已经研究过我知道erorr“无法在线程中创建未调用Looper.prepare()的处理程序”与代码未在UI线程上运行相关,但它也说它无法找到mapbox小部件。

mapbox xamarin文档中的示例是指在活动中使用地图的时候,但是我在运行时创建它作为自定义渲染器的一部分,所以我不确定如何实现de onCreate()onPause() onDestroy()..等功能。

所以,我失踪了,或者我做错了。

1 个答案:

答案 0 :(得分:1)

  

Android.Views.InflateException:二进制XML文件行#1:错误膨胀类com.mapbox.mapboxsdk.maps.widgets.UserLocationView ---&gt; Java.Lang.RuntimeException:无法在未调用Looper.prepare()的线程内创建处理程序

尝试在主线程委托中移动查看通胀

private async void SetupUserInterface()
{
   var activity = this.Context as Activity;
   Device.BeginInvokeOnMainThread(async() =>
   {
       view = activity.LayoutInflater.Inflate(Resource.Layout.mapLayout, this, false);
       // instanciando el mapa
       map = FindViewById<MapView>(Resource.Id.mapView);
       map.StyleUrl = Mapbox.Constants.Style.Emerald;
       var mapboxMap = await map.GetMapAsync();
       var position = new CameraPosition.Builder()
       .Target(new LatLng(41.885, -87.679))
       .Zoom(11)
       .Build();
       mapboxMap.AnimateCamera(CameraUpdateFactory.NewCameraPosition(position), 2500);
   });
}