正如您所说,Android Maps API v2 目前不直接支持使用边界和倾斜信息为相机设置动画。
一种解决方法是使用以下步骤:
- 使用边界执行您想要执行的相机动画,但忽略倾斜
- 监听上述摄像机动画结束,获取当前摄像机位置,然后进行倾斜
这具有将相机移动到边界同时向下看的效果(即倾斜 = 0),然后将相机倾斜到位。我发现这在某些用例中效果很好,实际上看起来不错,但在其他用例中却有点尴尬。它可能适用于您的特定用例,也可能不适用。
为了实现这一点,让我们假设您有一个主类 MapScreen.java,其中实现了您的地图。您需要对其进行更改以包含摄像头侦听器接口、对摄像头位置的引用、对您的活动的引用、要使用的初始倾斜值(您可以在运行时交替设置)和默认摄像头填充:
public class MapScreen extends FragmentActivity implements GoogleMap.OnCameraChangeListener {
...
private GoogleMap map;
public static CameraPosition lastCameraPosition;
public static MapScreen mapScreen;
public static float CAMERA_INITIAL_TILT = 30.0f;
public static int CAMERA_PADDING = 100;
...
public void onCreate(Bundle savedInstanceState) {
...
mapScreen = this;
...
//Set up map object here like normal
map = ((SupportMapFragment)(getSupportFragmentManager().findFragmentById(R.id.map))).getMap();
...
//Set camera change listener
map.setOnCameraChangeListener(this);
}
...
}
在这个类中,您还需要添加一个方法来在第一个动画停止时监听并保存相机的位置:
@Override
public void onCameraChange(CameraPosition position) {
//Save the last camera position so we can reference it when tilting the camera following animations
lastCameraPosition = position;
}
此外,添加一个您可以引用的内部类,该类在第一个动画完成后执行倾斜(稍微延迟以获得正确的 CameraPosition):
public class tiltOnFinishAnimation implements CancelableCallback {
@Override
public void onCancel() {
//Do nothing
}
@Override
public void onFinish() {
//We want to run the tilt animation, but the CameraPosition needed to center the camera in the right place
//is only available after the onFinish() method completes. So, we delay this by 10 ms to let the CameraPosition update
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
public void run() {
mapScreen.runOnUiThread(new Runnable() {
public void run() {
if(lastCameraPosition != null){
//Finish with a tilt
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(lastCameraPosition.target)
.zoom(lastCameraPosition.zoom)
.bearing(lastCameraPosition.bearing)
.tilt(CAMERA_INITIAL_TILT)
.build();
//Perform the tilt!
mapScreen.map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}
}
});
}
}, 10);
}
}
最后,当您想要移动相机时,执行您的正常代码,但首先确定根据方向正确设置相机动画所需的一些地图视图属性,并包含对在动画第一部分执行时执行的回调的引用没有倾斜停止:
//Get the View height and width, so we don't exceed the screen size after padding for the camera updates
int width;
int height;
if(mapFragment != null){
width = mapFragment.getView().getWidth();
height = mapFragment.getView().getHeight();
}else{
//If the map fragment hasn't been instantiated yet, use the entire display
if (android.os.Build.VERSION.SDK_INT >= 13){
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
width = size.x;
height = size.y;
}else{
Display display = getWindowManager().getDefaultDisplay();
width = display.getWidth();
height = display.getHeight();
}
}
if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){
//Use verticle size for padding
CAMERA_PADDING = (int) (height * 0.2f);
}else{
//Use horizontal size for padding
CAMERA_PADDING = (int) (width * 0.2f);
}
//Your code
markerList.add(m);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (Marker marker : markerList) {
builder.include(marker.getPosition());
}
LatLngBounds bounds = builder.build();
//Here's the new code below that triggers first the movement to the bounds, then the tilt (as a callback)
map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, width, height, CAMERA_PADDING), new tiltOnFinishAnimation());