Android: Re-use support map fragment inside viewpager fragment to keep FULL state -
i have application uses actionbarsherlock , google maps. have 3 main tabs in application , when navigate 2 tabs away, first tab destroyed. set setoffscreenpagelimit() 2 fix issue correctly , when users map view map empty , non-responsive. keep fragments in array inside actionbar activity try keep them being destroyed used work previous version of google play in moving 7.0.0 had restructure code. rather inexperienced fragments issue may lie there, though zoom , position of map maintained , nothing else (options, markers, etc..)
my code follows:
edit:
when come back, map saves zoom , looking, listeners , markers gone. tasks use map no longer connected
// actionbaractivity.java
public class actionbaractivity extends sherlockfragmentactivity implements tablistener, onpagechangelistener { viewpager mviewpager; string pagestring = "map_view"; // holder fragments used list<sherlockfragment> frags; @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.activity_action_bar); mviewpager = (viewpager) findviewbyid(r.id.pager); // *** code work without following line *** mviewpager.setoffscreenpagelimit(2); mviewpager.setadapter(new mypageradapter(this, getsupportfragmentmanager())); // actionbar actionbar bar = getsupportactionbar(); // tabs actionbar.tab maptab = bar.newtab() .seticon(r.drawable.ic_action_map) .settablistener(this) .settag("map"); actionbar.tab listtab = bar.newtab() .seticon(r.drawable.ic_action_view_as_list) .settablistener(this) .settag("list"); // tabs actionbar.tab photofeedtab = bar.newtab() .seticon(r.drawable.ic_action_camera) .settablistener(this) .settag("photo"); bar.setnavigationmode(actionbar.navigation_mode_tabs); bar.addtab(maptab); bar.addtab(listtab); bar.addtab(photofeedtab); frags = arrays.aslist(null, null, null); } @override protected void onresume() { super.onresume(); mviewpager.setonpagechangelistener(this); } @override protected void onpause() { super.onpause(); mviewpager.setonpagechangelistener(null); } private class mypageradapter extends fragmentstatepageradapter { private final string[] mpagetitles; public mypageradapter(context context, fragmentmanager fm) { super(fm); mpagetitles = context.getresources().getstringarray(r.array.pagetitle); } @override public charsequence getpagetitle(int position) { return mpagetitles[position]; } @override public int getcount() { return mpagetitles.length; } @override public fragment getitem(int position) { fragment f = null; switch (position) { case 0: pagestring = "map_view"; if(frags.get(0) == null) { viewmap vm = new viewmap(); vm.setretaininstance(true); frags.set(0, vm); } f = frags.get(0); // pass through bundle holding lat/long // move camera (if present) bundle showdata = getintent().getextras(); if (showdata != null) { f.setarguments(showdata); } break; case 1: pagestring = "list_view"; if(frags.get(1) == null) { frags.set(1, new listviewhubba()); } f = frags.get(1); break; case 2: pagestring = "photo_feed"; if(frags.get(2) == null) { frags.set(2, new photofeedlist()); } f = frags.get(2); break; } return f; } } public void onpagescrollstatechanged(int arg0) { } public void onpagescrolled(int arg0, float arg1, int arg2) { } public void onpageselected(int position) { position = position % getsupportactionbar().getnavigationitemcount(); getsupportactionbar().setselectednavigationitem(position); } public void ontabselected(tab tab, fragmenttransaction ft) { mviewpager.setcurrentitem(tab.getposition()); } public void ontabunselected(tab tab, fragmenttransaction ft) { } public void ontabreselected(tab tab, fragmenttransaction ft) { } }
// viewmap.java
public class viewmap extends sherlockfragment { public googlemap mmap; private view rootview = null; context context; private view v; progressdialog progressdialog; boolean fetched = false; supportmapfragment fragment; @override public void onactivitycreated(bundle savedinstancestate) { super.onactivitycreated(savedinstancestate); fragmentmanager fm = getchildfragmentmanager(); fragment = getmapfragment(); if (fragment == null) { log.i("debug", "fragment null."); fragment = supportmapfragment.newinstance(); fragment.setretaininstance(true); fm.begintransaction().replace(r.id.map_container, fragment).commit(); } else { log.i("debug", "fragment not null."); } /** * @ time google play services not initialize map * , add ever want in onresume() or onstart() */ } @override public void onresume() { super.onresume(); setupmapifneeded(); } public view oncreateview(final layoutinflater inflater, final viewgroup container, bundle savedinstancestate) { super.oncreateview(inflater, container, savedinstancestate); context = getactivity().getapplicationcontext(); if(rootview == null) { rootview = inflater.inflate(r.layout.view_map_activity, container, false); } else { log.i("debug", "non null root view."); } return rootview; } public void setupmapifneeded() { if (mmap == null) { mmap = fragment.getmap(); fetched = false; } // check if successful in obtaining map. // , reload if haven't fetched if (mmap != null && !fetched) { mmap.setmaptype(googlemap.map_type_normal); ishybrid = false; mmap.setmylocationenabled(true); // check if current location available, otherwise default riley locationmanager lm = (locationmanager) context.getsystemservice(context.location_service); location location = lm.getlastknownlocation(locationmanager.gps_provider); latlng center; if (location != null) { // current location info center = new latlng(location.getlatitude(), location.getlongitude()); } else { // default riley center = new latlng(42.4409010, -83.3978000); } // set camera position cameraposition cameraposition = new cameraposition.builder() .target(center) .zoom(camera_zoom) .bearing(0) .tilt(30) .build(); mmap.animatecamera(cameraupdatefactory .newcameraposition(cameraposition)); /** * show loading message if first time fetching. */ progressdialog = progressdialog.show(getactivity(), "", "fetching spots...", true); spot.getallspots(mmap, getactivity().getapplicationcontext(), progressdialog); fetched = true; //... custom map options here ... } } private supportmapfragment getmapfragment() { fragmentmanager fm = null; if (build.version.sdk_int < build.version_codes.lollipop) { log.i("debug", "using getfragmentmanager"); fm = getfragmentmanager(); } else { log.i("debug", "using getchildfragmentmanager"); fm = getchildfragmentmanager(); } return (supportmapfragment) fm.findfragmentbyid(r.id.map_container); } }
// view_map_activity.xml
<?xml version="1.0" encoding="utf-8"?> <relativelayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/map_view_container" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#000"> <relativelayout android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/map_container"> <!-- map fragment go here --> </relativelayout> </relativelayout>
i not getting error/crashes when map view furthest right tab, zoom , location still there of markers gone. have workaround add them when fragment navigated -- slow since have ton of markers.
does know of way keep nested child supportmapfragment around? have been working on long time , use help...
you can use:
setretaininstance(true);
in oncreate() method ask supportmapfragment retain points etc when recycling map. anyway require time save , restore thousands of markers, , have no alternatives, big data big data :d
edit: anyway seems retaining instance... work?
edit2: looking @ maps demo, there 1 "mapretain" running on device work. maybe of touches fragments , "supportmapfragment.newinstance()" breaks everything...
/** * shows how retain map across activity restarts (e.g., screen rotations), can * faster relying on state serialization. */ public class retainmapdemoactivity extends fragmentactivity implements onmapreadycallback { @override protected void oncreate(bundle savedinstancestate) { super.oncreate(savedinstancestate); setcontentview(r.layout.basic_demo); supportmapfragment mapfragment = (supportmapfragment) getsupportfragmentmanager().findfragmentbyid(r.id.map); if (savedinstancestate == null) { // first incarnation of activity. mapfragment.setretaininstance(true); } mapfragment.getmapasync(this); } @override public void onmapready(googlemap map) { map.addmarker(new markeroptions().position(new latlng(0, 0)).title("marker")); } }
Comments
Post a Comment