Fix Map View to improve the initial camera position after screen rotation.

If showing a marker, after rotation, will zoom to the marker.
If showing a track, after rotation, will zoom to the current location
if is recording and is in tracking mode, else will zoom to the track.
This commit is contained in:
Jimmy Shih
2013-05-29 10:34:15 -07:00
parent 4f13b62a81
commit 55861ecf0e
3 changed files with 67 additions and 66 deletions
@@ -83,7 +83,6 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
private static final String CURRENT_LOCATION_KEY = "current_location_key"; private static final String CURRENT_LOCATION_KEY = "current_location_key";
private static final String private static final String
KEEP_CURRENT_LOCATION_VISIBLE_KEY = "keep_current_location_visible_key"; KEEP_CURRENT_LOCATION_VISIBLE_KEY = "keep_current_location_visible_key";
private static final String ZOOM_TO_CURRENT_LOCATION_KEY = "zoom_to_current_location_key";
private static final float DEFAULT_ZOOM_LEVEL = 18f; private static final float DEFAULT_ZOOM_LEVEL = 18f;
@@ -114,22 +113,6 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
*/ */
private boolean keepCurrentLocationVisible; private boolean keepCurrentLocationVisible;
/**
* True to zoom/center the current location when it is available.
* <p>
* Set to true when <br>
* 1. user clicks on the my location button <br>
* 2. first location during a recording <br>
* Set to false when <br>
* 1. showing a marker <br>
* 2. user manually zooms/pans <br>
* 3. after zooming to the current location <br>
* <p>
* The last one is to support the use case of zooming only once. After zoom,
* set it to false. E.g., only zoom to the first location during a recording.
*/
private boolean zoomToCurrentLocation;
private OnLocationChangedListener onLocationChangedListener; private OnLocationChangedListener onLocationChangedListener;
// Current track // Current track
@@ -181,9 +164,8 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
public void onLocationChanged(Location location) { public void onLocationChanged(Location location) {
myTracksLocationManager.close(); myTracksLocationManager.close();
keepCurrentLocationVisible = true; keepCurrentLocationVisible = true;
zoomToCurrentLocation = true;
setCurrentLocation(location); setCurrentLocation(location);
updateCurrentLocation(); updateCurrentLocation(true);
} }
}); });
} }
@@ -199,9 +181,12 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
if (savedInstanceState != null) { if (savedInstanceState != null) {
keepCurrentLocationVisible = savedInstanceState.getBoolean( keepCurrentLocationVisible = savedInstanceState.getBoolean(
KEEP_CURRENT_LOCATION_VISIBLE_KEY, false); KEEP_CURRENT_LOCATION_VISIBLE_KEY, false);
zoomToCurrentLocation = savedInstanceState.getBoolean(ZOOM_TO_CURRENT_LOCATION_KEY, false); if (keepCurrentLocationVisible) {
Location location = (Location) savedInstanceState.getParcelable(CURRENT_LOCATION_KEY); Location location = (Location) savedInstanceState.getParcelable(CURRENT_LOCATION_KEY);
setCurrentLocation(location); if (location != null) {
setCurrentLocation(location);
}
}
} }
/* /*
@@ -260,7 +245,6 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
if (isResumed() && keepCurrentLocationVisible && currentLocation != null if (isResumed() && keepCurrentLocationVisible && currentLocation != null
&& !isLocationVisible(currentLocation)) { && !isLocationVisible(currentLocation)) {
keepCurrentLocationVisible = false; keepCurrentLocationVisible = false;
zoomToCurrentLocation = false;
} }
} }
}); });
@@ -296,12 +280,22 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
// setWarningMessage depends on resumeTrackDataHub being invoked beforehand // setWarningMessage depends on resumeTrackDataHub being invoked beforehand
setWarningMessage(isGpsProviderEnabled); setWarningMessage(isGpsProviderEnabled);
updateCurrentLocation();
if (markerId == -1L && isInTrackingMode()) {
updateCurrentLocation(true);
} else {
if (googleMap != null) {
googleMap.moveCamera(
CameraUpdateFactory.newLatLngZoom(getDefaultLatLng(), googleMap.getMinZoomLevel()));
}
}
} }
@Override @Override
public void onSaveInstanceState(Bundle outState) { public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
outState.putBoolean(KEEP_CURRENT_LOCATION_VISIBLE_KEY, keepCurrentLocationVisible);
if (currentLocation != null) { if (currentLocation != null) {
/* /*
* currentLocation is a MyTracksLocation object, which cannot be * currentLocation is a MyTracksLocation object, which cannot be
@@ -310,8 +304,6 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
*/ */
outState.putParcelable(CURRENT_LOCATION_KEY, new Location(currentLocation)); outState.putParcelable(CURRENT_LOCATION_KEY, new Location(currentLocation));
} }
outState.putBoolean(KEEP_CURRENT_LOCATION_VISIBLE_KEY, keepCurrentLocationVisible);
outState.putBoolean(ZOOM_TO_CURRENT_LOCATION_KEY, zoomToCurrentLocation);
} }
@Override @Override
@@ -384,14 +376,11 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
public void onSelectedTrackChanged(final Track track) { public void onSelectedTrackChanged(final Track track) {
if (isResumed()) { if (isResumed()) {
currentTrack = track; currentTrack = track;
boolean hasTrack = track != null; mapOverlay.setShowEndMarker(!isSelectedTrackRecording());
if (hasTrack) { if (markerId != -1L) {
mapOverlay.setShowEndMarker(!isSelectedTrackRecording()); showMarker(markerId);
if (markerId != -1L) { } else {
// Show the marker if (!isInTrackingMode()) {
showMarker(markerId);
} else {
// Show the track
showTrack(); showTrack();
} }
} }
@@ -447,12 +436,13 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
if (hasStartMarker) { if (hasStartMarker) {
reloadPaths = false; reloadPaths = false;
} }
if (!isSelectedTrackRecording() || isSelectedTrackPaused()) {
lastTrackPoint = null; if (lastTrackPoint != null && isSelectedTrackRecording()) {
} boolean firstLocation = setCurrentLocation(lastTrackPoint);
if (lastTrackPoint != null) { if (firstLocation) {
setCurrentLocation(lastTrackPoint); keepCurrentLocationVisible = true;
updateCurrentLocation(); }
updateCurrentLocation(firstLocation);
setWarningMessage(true); setWarningMessage(true);
} }
} }
@@ -542,32 +532,28 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
return trackDataHub != null && trackDataHub.isSelectedTrackRecording(); return trackDataHub != null && trackDataHub.isSelectedTrackRecording();
} }
/**
* Returns true if the selected track is paused. Needs to be synchronized
* because trackDataHub can be accessed by multiple threads.
*/
private synchronized boolean isSelectedTrackPaused() {
return trackDataHub != null && trackDataHub.isSelectedTrackPaused();
}
/** /**
* Sets the current location. * Sets the current location.
* *
* @param location the location * @param location the location
* @return true if this is the first location
*/ */
private void setCurrentLocation(Location location) { private boolean setCurrentLocation(Location location) {
// If recording, zoom to the first location boolean firstLocation = false;
if (isSelectedTrackRecording() && currentLocation == null && location != null) { if (currentLocation == null && location != null) {
keepCurrentLocationVisible = true; firstLocation = true;
zoomToCurrentLocation = true;
} }
currentLocation = location; currentLocation = location;
return firstLocation;
} }
/** /**
* Updates the current location and zoom to it if necessary. * Updates the current location.
*
* @param forceZoom true to force zoom to the current location regardless of
* the keepCurrentLocationVisible policy
*/ */
private void updateCurrentLocation() { private void updateCurrentLocation(final boolean forceZoom) {
getActivity().runOnUiThread(new Runnable() { getActivity().runOnUiThread(new Runnable() {
public void run() { public void run() {
if (!isResumed() || googleMap == null || onLocationChangedListener == null if (!isResumed() || googleMap == null || onLocationChangedListener == null
@@ -575,11 +561,9 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
return; return;
} }
onLocationChangedListener.onLocationChanged(currentLocation); onLocationChangedListener.onLocationChanged(currentLocation);
if (zoomToCurrentLocation if (forceZoom || (keepCurrentLocationVisible && !isLocationVisible(currentLocation))) {
|| (keepCurrentLocationVisible && !isLocationVisible(currentLocation))) {
LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()); LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM_LEVEL)); googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM_LEVEL));
zoomToCurrentLocation = false;
} }
}; };
}); });
@@ -649,7 +633,6 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
Location location = waypoint.getLocation(); Location location = waypoint.getLocation();
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
keepCurrentLocationVisible = false; keepCurrentLocationVisible = false;
zoomToCurrentLocation = false;
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM_LEVEL); CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM_LEVEL);
googleMap.moveCamera(cameraUpdate); googleMap.moveCamera(cameraUpdate);
} }
@@ -662,16 +645,20 @@ public class MyTracksMapFragment extends SupportMapFragment implements TrackData
*/ */
private LatLng getDefaultLatLng() { private LatLng getDefaultLatLng() {
MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(getActivity()); MyTracksProviderUtils myTracksProviderUtils = MyTracksProviderUtils.Factory.get(getActivity());
Track track = myTracksProviderUtils.getLastTrack(); Location location = myTracksProviderUtils.getLastValidTrackPoint();
if (track != null) { if (location != null) {
Location location = myTracksProviderUtils.getLastValidTrackPoint(track.getId()); return new LatLng(location.getLatitude(), location.getLongitude());
if (location != null) {
return new LatLng(location.getLatitude(), location.getLongitude());
}
} }
return new LatLng(DEFAULT_LATITUDE, DEFAULT_LONGITUDE); return new LatLng(DEFAULT_LATITUDE, DEFAULT_LONGITUDE);
} }
/**
* Returns true if in tracking mode.
*/
private boolean isInTrackingMode() {
return keepCurrentLocationVisible && currentLocation != null && isSelectedTrackRecording();
}
/** /**
* Returns true if the location is visible. Needs to run on the UI thread. * Returns true if the location is visible. Needs to run on the UI thread.
* *
@@ -252,6 +252,12 @@ public interface MyTracksProviderUtils {
*/ */
public Location getLastValidTrackPoint(long trackId); public Location getLastValidTrackPoint(long trackId);
/**
* Gets the last valid location.
*/
public Location getLastValidTrackPoint();
/** /**
* Creates a location cursor. The caller owns the returned cursor and is * Creates a location cursor. The caller owns the returned cursor and is
* responsible for closing it. * responsible for closing it.
@@ -816,6 +816,14 @@ public class MyTracksProviderUtilsImpl implements MyTracksProviderUtils {
return findTrackPointBy(selection, selectionArgs); return findTrackPointBy(selection, selectionArgs);
} }
@Override
public Location getLastValidTrackPoint() {
String selection = TrackPointsColumns._ID + "=(select max(" + TrackPointsColumns._ID + ") from "
+ TrackPointsColumns.TABLE_NAME + " WHERE " + TrackPointsColumns.LATITUDE + "<="
+ MAX_LATITUDE + ")";
return findTrackPointBy(selection, null);
}
@Override @Override
public Cursor getTrackPointCursor( public Cursor getTrackPointCursor(
long trackId, long startTrackPointId, int maxLocations, boolean descending) { long trackId, long startTrackPointId, int maxLocations, boolean descending) {