Google 地图 Android API v2 - 恢复地图状态

7
我正在使用Google Maps Android API v2构建一个非常简单的地图应用。正如预期的那样,当用户离开并返回应用程序时,由于活动被销毁和重新创建,他们所做的任何位置、缩放等更改都会丢失。
我知道我可以在onPause()中以编程方式保存地图的相机状态(例如作为共享首选项中的值),并在onResume()中恢复它,但是API是否有任何内置机制来保持地图状态在活动启动之间持久化?
4个回答

9
我认为你不能直接保存地图上当前的位置/缩放/角度,但是你可以保存包含这些信息的CameraPosition对象。你可以在onDestroy()方法中编写一个函数,用于获取地图上的CameraPosition并将其存储在SharedPreferences中。然后,在onCreate()方法中,你可以重新创建CameraPosition对象,并从SharedPreferences中获取之前保存的信息(在地图被实例化之后)。具体操作请参考:http://developer.android.com/reference/com/google/android/gms/maps/model/CameraPosition.html
// somewhere in your onDestroy()
@Override
protected void onDestroy() {
    CameraPosition mMyCam = MyMap.getCameraPosition();
    double longitude = mMyCam.target.longitude;
    (...)

    SharedPreferences settings = getSharedPreferences("SOME_NAME", 0);
    SharedPreferences.Editor editor = settings.edit();
    editor.putDouble("longitude", longitude);
    (...) //put all other values like latitude, angle, zoom...
    editor.commit();
}

在您的 onCreate()

SharedPreferences settings = getSharedPreferences("SOME_NAME", 0);
// "initial longitude" is only used on first startup
double longitude = settings.getDouble("longitude", "initial_longitude");  
(...)  //add the other values

LatLng startPosition = new LatLng() //with longitude and latitude


CameraPosition cameraPosition = new CameraPosition.Builder()
.target(startPosition)      // Sets the center of the map to Mountain View
.zoom(17)                   // Sets the zoom
.bearing(90)                // Sets the orientation of the camera to east
.tilt(30)                   // Sets the tilt of the camera to 30 degrees
.build();                   // Creates a CameraPosition from the builder

创建一个新的cameraPosition并对其进行动画处理。请确保在此时地图已经实例化。
 map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));

3
onSaveInstanceState()期间将CameraPosition保存为可包装对象似乎可以在更改方向时起作用,但当用户通过触摸返回按钮退出时,不会调用它。 在那里,我得到了onPause()onStop()onDestroy() - 这些都没有给我访问实例状态Bundle的权限。 我正在学习状态管理,所以如果我理解有误,请谅解。 - David Gassner
我有什么遗漏吗?不能保证onDestroy方法一定会被调用,因此最好在onPause方法中保存数据。同样,在onResume方法中检索数据比在onCreate方法中更好的实践。 - Hanu
除了您提到的onDestroy不会被调用的异议外,这不会有任何影响。我们使用onCreate/onDestroy是因为我们只想在应用程序启动时重新创建地图状态。然而,将这些块移动到onResumeonPause也可以起作用。 - longi

1

感谢2013年longi提供的答案,它对我很有帮助。为了更好地帮助他人,让我分享我的确切解决方案(基于longi的答案)。

在onStop()中保存相机位置:

@Override
protected void onStop() {
    super.onStop();

    CameraPosition mMyCam = mMap.getCameraPosition();
    double longitude = mMyCam.target.longitude;
    double latitude = mMyCam.target.latitude;
    float zoom = mMyCam.zoom;

    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putFloat("longitude", (float)longitude);
    editor.putFloat("latitude", (float)latitude);
    editor.putFloat("zoom", zoom);
    editor.apply();
}

在 onMapReady() 中获取相机位置:

@Override
public void onMapReady(GoogleMap googleMap) {

    mMap = googleMap;

    // Get previous (or default) camera position
    SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
    double longitude = sharedPref.getFloat("longitude", DEFAULT_LONGITUDE);
    double latitude = sharedPref.getFloat("latitude", DEFAULT_LATITUDE);
    float zoom = sharedPref.getFloat("zoom", DEFAULT_ZOOM);
    LatLng startPosition = new LatLng(latitude, longitude);
    CameraPosition cameraPosition = new CameraPosition.Builder()
            .target(startPosition)
            .zoom(zoom)
            .build();
    mMap.moveCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}

1
根据保留MapFragment实例的指示,您可以为MapFragmentSupportMapFragment调用setRetainInstance(true);以在设备方向更改后保留相机状态和标记。然而,如果您想在应用程序启动之间保持状态,那么SharedPreferences是正确的方法,如longilong所述。

0

API 中没有针对此用例的内容。

您可以尝试使用此库:https://github.com/fsilvestremorais/android-complex-preferences

它不像只需编写一堆 SharedPreferences.Editor.put... 来保存 CameraPosition 中的值,那样高效,因为它在内部使用 Gson,但如果您需要保存和恢复更复杂的对象,则可以节省一些时间。

无论如何,您也可以在 gmaps-api-issues(或 Android Maps Extensions)上发布功能请求。这肯定是缺少的,以便轻松持久化简单对象(CameraPositionLatLngLatLngBounds)。


作为另一种选择:我维护TypedPreferences库。 - JJD
1
@JJD 嘿,Tobias,我以前见过它,但是你的库不再有 ObjectPreference 了吗?无论如何,我现在建议使用 Hrisey@Preferences 注释。你看过了吗? - MaciejGórski
不,TypedPreferences 只支持“基本类型”。我不知道 Hrisey - 谢谢分享。我会去看看。 - JJD

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接