MapView控件未在ViewPager中加载

时间:2014-06-13 16:44:44

标签: android android-viewpager xamarin android-mapview

我有一个MapView控件,我试图在ViewPager中加载。 ViewPager加载了布局视图,而不是片段,因为ViewPager本身位于片段中,我想避免片段场景中的片段。

这是ViewPager的适配器,它将地图加载为第4个屏幕:

public class AmbientPagerAdapter : PagerAdapter {
        private ViewPagerWithMap pager;
        private CurrentLocationStatistics ambientData;
        private AmbientSearchBuilder searchBuilder;
        private AmbientSearchIndicatorBuilder searchIndicatorBuilder;
        private AmbientIndicatorBuilder indicatorBuilder;
        private AmbientMapBuilder mapBuilder;
        private Bundle savedInstanceState;

        public AmbientPagerAdapter(View view, CurrentLocationStatistics ambientData, Bundle savedInstanceState) {
            this.pager = view.FindViewById<ViewPagerWithMap> (Resource.Id.ambient_pager);
            this.ambientData = ambientData;
            this.savedInstanceState = savedInstanceState;

            SetupEvents ();
        }

        private void SetupEvents () {
            pager.Touch += (object sender, View.TouchEventArgs e) => {
                pager.Parent.RequestDisallowInterceptTouchEvent(true);
                e.Handled = false;
            };
        }

        #region Setup Views

        public override Java.Lang.Object InstantiateItem(View collection, int position) {
            var layoutInflater = (LayoutInflater)ApplicationContext.Activity.GetSystemService (Context.LayoutInflaterService);
            View view = null;
            switch (position) {
            case 0: 
                view = layoutInflater.Inflate (Resource.Layout.AmbientSearch, null);
                searchBuilder = new AmbientSearchBuilder (view, ambientData);
                break;
            case 1: 
                view = layoutInflater.Inflate (Resource.Layout.AmbientSearchIndicators, null);
                searchIndicatorBuilder = new AmbientSearchIndicatorBuilder (view, ambientData);
                break;
            case 2: 
                view = layoutInflater.Inflate (Resource.Layout.AmbientIndicators, null);
                indicatorBuilder = new AmbientIndicatorBuilder (view, ambientData);
                break;
            case 3: 
                view = layoutInflater.Inflate (Resource.Layout.AmbientMap, null);
                mapBuilder = new AmbientMapBuilder (view, ambientData, savedInstanceState);
                break;
            }

            // Add view to pager
            var viewPager = collection.JavaCast<ViewPager>();
            viewPager.AddView(view);

            return view;
        }

        public void Update (CurrentLocationStatistics ambientData) {
            this.ambientData = ambientData;
            if (searchBuilder != null) {
                searchBuilder.Update (ambientData);
            }
            if (searchIndicatorBuilder != null) {
                searchIndicatorBuilder.Update (ambientData);
            }
            if (indicatorBuilder != null) {
                indicatorBuilder.Update (ambientData);
            }
            if (mapBuilder != null) {
                mapBuilder.Update (ambientData);
            }
        }

        #endregion

        #region Infrastructure

        public override void DestroyItem(View collection, int position, Java.Lang.Object view) {
            var viewPager = collection.JavaCast<ViewPager>();
            viewPager.RemoveView (view as View);
            if (position == 3 && mapBuilder != null) {
                mapBuilder.OnDestroy ();
            }
        }

        public override bool IsViewFromObject(View view, Java.Lang.Object obj) {
            return view == obj;
        }

        public override IParcelable SaveState() {
            return null;
        }

        public override void StartUpdate(View arg0) {
        }

        public override void FinishUpdate(View arg0) {
        }

        public void UpdateVisibleItem (int index) {
            pager.SetCurrentItem (index, false);
        }

        public override int Count {
            get {
                return 4;
            }
        }

        #endregion

        public AmbientSearchBuilder SearchBuilder { get { return searchBuilder; } }
        public AmbientMapBuilder MapBuilder { get { return mapBuilder; } }
    }

一旦用户滑动到第3个屏幕,它就会实例化地图,因为ViewPager需要加载下一个屏幕,以便在滑过时可以同时显示两者(默认的ViewPager行为)。这可能是问题的一部分,当它还没有在视野中时加载地图?

下面是设置MapView的类。生命周期事件由托管ViewPager的片段调用。

public class AmbientMapBuilder : AmbientBuilderBase {
        private View view;
        private TouchMapView mapView;
        private PropertyMapAdapter adapter;
        private Geolocation initialLocation;
        private CameraPosition lastCamera;
        private TinyMessageSubscriptionToken filterToken;

        public AmbientMapBuilder(View view, CurrentLocationStatistics ambientData, Bundle savedInstanceState = null) : base(ambientData) {
            this.view = view;
            this.mapView = view.FindViewById<TouchMapView> (Resource.Id.map);
            mapView.OnCreate (savedInstanceState);
            //MapsInitializer.Initialize (ApplicationContext.Activity);
        }

        public void Update (CurrentLocationStatistics ambientData) {
            this.ambientData = ambientData;
        }

        #region Lifecycle Events

        public void OnResume () {
            if (mapView != null)
                mapView.OnResume ();

            if (lastCamera != null) {
                if (adapter != null)
                    adapter.MoveMapToPosition (lastCamera);
                lastCamera = null;
            }
        }

        public void OnPause () {
            mapView.OnPause ();
            lastCamera = mapView.Map.CameraPosition;
            if (filterToken != null) {
                filterToken.Dispose ();
                filterToken = null;
            }
        }

        public void OnSaveInstanceState (Bundle outState) {
            var map = mapView;
            if (map != null)
                map.OnSaveInstanceState (outState);
        }

        public void OnLowMemory () {
            if (mapView != null) {
                mapView.OnLowMemory ();
            }
        }

        public void OnDestroy () {
            if (mapView != null) {
                mapView.OnDestroy ();
            }
        }

        #endregion

        public bool MapIsLoaded { get; set; }

        public PropertyMapAdapter MapAdapter {
            get { return adapter; }
        }

        public View View {
            get { return view; }
        }

        public TouchMapView MapView {
            get { return mapView; }
        }
    }

最后,这是地图的布局xml:

<RPR.Mobile.Droid.Widget.TouchMapView xmlns:map="http://schemas.android.com/apk/res-auto"
        android:id="@+id/map"
        map:cameraTargetLat="37.09024"
        map:cameraTargetLng="-95.712891"
        map:cameraZoom="3"
        map:uiCompass="false"
        map:uiRotateGestures="false"
        map:uiScrollGestures="true"
        map:uiTiltGestures="false"
        map:uiZoomGestures="true"
        map:uiZoomControls="false"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

下面是地图的样子,它只显示网格线和灰色背景但没有地图,地图无法与之互动。

enter image description here

任何想法是什么问题?

1 个答案:

答案 0 :(得分:4)

此问题的产生是由于片段的生命周期与ViewPager中mapView的实例化不对齐,特别是在mapView设置之前调用了fragment.OnResume方法,因此从未调用过mapView.OnResume()。我需要在mapView.OnCreate()之后手动调用mapView.OnResume()然后一切都工作得很好。