My activity can display map view of places. I toggle the map view by sliding a fragment (containing the map) into a FragmentLayout container in the activity. When it has content, this layout covers a list layout. The animation toggles the map view in/out correctly.
The first time the map transitions in, the map camera is focused on the current location and onMapClick() works as expected.
Subsequent times when the map transitions in, the camera is zoomed all the way out with North/South Atlantic Oceans and Africa in view. And the onMapClick() event doesn't fire. I've tried changing the map's UiSettings just to see if I have any programmatic control on subsequent transitions, but that didn't work.
Here's how I transition the map in/out in my activity (which visually works correctly)
void toggleMapView() {
log("toggleMapView()");
if (!isMapShowing) {
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.addToBackStack(null);
// fades in, then fades out on back key
transaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_in_left,
android.R.anim.slide_out_right, android.R.anim.slide_out_right);
// mapFragment is assigned in onCreated()
transaction.replace(R.id.framelayout_fragment_container, mapfragment, "MAPTAG");
transaction.commit();
} else
this.onBackPressed();
isMapShowing = !isMapShowing;
}
Here's my onMapReady() in the fragment:
@Override
public void onMapReady(GoogleMap googleMap) {
log("onMapReady()");
mMap = googleMap;
LatLng currentLatLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//marker = mMap.addMarker(new MarkerOptions().position(currentLatLng).title("").draggable(true).visible(false));
mMap.setMinZoomPreference(4.0f);
mMap.setMaxZoomPreference(20.0f);
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 15.0f));
UiSettings ui = mMap.getUiSettings();
ui.setCompassEnabled(false);
ui.setRotateGesturesEnabled(false);
ui.setTiltGesturesEnabled(false);
ui.setZoomControlsEnabled(false);
mMap.setOnMapClickListener(this);
}
I log all of my methods so I can see the sequence of calls. Here's what they look like every time the map transitions in:
D/ << GET_PLACE >>: onCallbackFromFragment()
D/ << MAP_P_Frag >>: setCurrentLocation()
D/ << GET_PLACE >>: toggleMapView()
D/ << MAP_P_Frag >>: onAttach()
D/ << MAP_P_Frag >>: onCreate()
D/ << MAP_P_Frag >>: onCreateView()
D/ << MAP_P_Frag >>: onstart()
D/ << MAP_P_Frag >>: onResume() [only calls setCamera]
D/ << MAP_P_Frag >>: setCamera() [calls onMapReady]
D/ << MAP_P_Frag >>: onMapReady()
The map is loaded one time in onCreateView(), which should have resulted in a call to onMapReady() during the first transition.
if (mapFragment == null) {
mapFragment = SupportMapFragment.newInstance();
mapFragment.getMapAsync(this);
}
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.replace(R.id.map_container, mapFragment).commit();
Since onResume() unconditionally calls -> setCamera() which in turn calls -> onMapReady(), I expected to see onMapReady() method called twice on the first transition...but I didn't.
I modified my setCamera() method to change the map's UiSettings instead of calling onMapReady().
After the edit, onMapReady() is only called once during the first transition, as expected. However, the attempt to change UiSettings during subsequent transitions had no effect. I set a breakpoint to ensure UiSettings were being called. I get no errors, and it has no effect.
public void setCamera() {
log("setCamera()");
if (mMap != null) {
UiSettings ui = mMap.getUiSettings();
ui.setCompassEnabled(true);
ui.setRotateGesturesEnabled(true);
ui.setTiltGesturesEnabled(true);
ui.setZoomControlsEnabled(true);
}
}
Finally, I eliminated the transition in toggleMapView() and did a simple fragment replace(), but it also has had no effect. I've also made sure that the key global variables "mMap" and "mapFragment" are only instantiated one time.
There's something about the state of the fragment or the map that I don't understand. Why don't I have programmatic control of the map after the first transition (or perhaps more accurately, after the initial map load)?