如何使用Google Maps for Android V2处理地图移动结束?

Ale*_*rov 44 android google-maps android-mapview google-maps-android-api-2

我想在地图中心更改后立即对地址进行地理编码.

如何使用适用于Android V2的新Google地图处理地图moveend?(我正在谈论案例,然后用户通过手指拖动地图)

pun*_*sta 47

查看新地图api.

 @Override
public void onMapReady(GoogleMap map) {
    mMap = map;

    mMap.setOnCameraIdleListener(this);
    mMap.setOnCameraMoveStartedListener(this);
    mMap.setOnCameraMoveListener(this);
    mMap.setOnCameraMoveCanceledListener(this);

    // Show Sydney on the map.
    mMap.moveCamera(CameraUpdateFactory
            .newLatLngZoom(new LatLng(-33.87365, 151.20689), 10));
}

@Override
public void onCameraMoveStarted(int reason) {

    if (reason == OnCameraMoveStartedListener.REASON_GESTURE) {
        Toast.makeText(this, "The user gestured on the map.",
                       Toast.LENGTH_SHORT).show();
    } else if (reason == OnCameraMoveStartedListener
                            .REASON_API_ANIMATION) {
        Toast.makeText(this, "The user tapped something on the map.",
                       Toast.LENGTH_SHORT).show();
    } else if (reason == OnCameraMoveStartedListener
                            .REASON_DEVELOPER_ANIMATION) {
        Toast.makeText(this, "The app moved the camera.",
                       Toast.LENGTH_SHORT).show();
    }
}

@Override
public void onCameraMove() {
    Toast.makeText(this, "The camera is moving.",
                   Toast.LENGTH_SHORT).show();
}

@Override
public void onCameraMoveCanceled() {
    Toast.makeText(this, "Camera movement canceled.",
                   Toast.LENGTH_SHORT).show();
}

@Override
public void onCameraIdle() {
    Toast.makeText(this, "The camera has stopped moving.",
                   Toast.LENGTH_SHORT).show();
}
Run Code Online (Sandbox Code Playgroud)

developers.google.com示例


AZ1*_*Z13 27

以下是确定拖动开始和拖动结束事件的可能解决方法:

您必须扩展SupportMapFragment或MapFragment.在onCreateView中,您必须将MapView包装在自定义的FrameLayout中(在下面的示例中是"TouchableWrapper"类),您可以在其中拦截触摸事件并识别是否点击了地图.如果你的"onCameraChange"被调用,只需检查是否按下了地图视图(在下面的示例中,这是变量"mMapIsTouched").

示例代码:

更新1:

  • 在getView()中返回原始创建的视图
  • 使用dispatchTouchEvent()而不是onInterceptTouchEvent()

自定义FrameLayout:

private class TouchableWrapper extends FrameLayout {

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mMapIsTouched = true;
                break;
            case MotionEvent.ACTION_UP:
                mMapIsTouched = false;
                break;
        }

        return super.dispatchTouchEvent(ev);

    }

}
Run Code Online (Sandbox Code Playgroud)

在您自定义的MapFragment中:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent, 
        Bundle savedInstanceState) {
    mOriginalContentView = super.onCreateView(inflater, parent, 
            savedInstanceState);

    mTouchView = new TouchableWrapper(getActivity());
    mTouchView.addView(mOriginalContentView);

    return mTouchView;
}

@Override
public View getView() {
    return mOriginalContentView;
}
Run Code Online (Sandbox Code Playgroud)

在你的相机更改回调方法:

private final OnCameraChangeListener mOnCameraChangeListener = 
        new OnCameraChangeListener() {

    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
        if (!mMapIsTouched) {
            refreshClustering(false);
        }
    }
};
Run Code Online (Sandbox Code Playgroud)


Mad*_*sen 25

已过时使用新的地图API.请参阅punksta的回答.

在使用上面的AZ13解决方案并遇到评论中提到的问题后,我创建了以下解决方案,可以更可靠地解决问题.但是,由于我在onRelease事件之后使用计时器来确定地图是否仍然是动画,因此此解决方案稍有延迟.

该代码可以通过以下链接在Github上找到:https://github.com/MadsFrandsen/MapStateListener

我的解决方案可以通过以下方式从活动中使用:

new MapStateListener(mMap, mMapFragment, this) {
  @Override
  public void onMapTouched() {
    // Map touched
  }

  @Override
  public void onMapReleased() {
    // Map released
  }

  @Override
  public void onMapUnsettled() {
    // Map unsettled
  }

  @Override
  public void onMapSettled() {
    // Map settled
  }
};
Run Code Online (Sandbox Code Playgroud)

  • 对我来说似乎工作正常,它对@ Az13解决方案有很好的增强:) (3认同)

Jan*_*usz 8

我会尝试onCameraChangeListener.每次完成摄像机的移动时都会调用监听器.听众还会给你新的位置.在我的测试中,在拖动过程中经常调用监听器,可能有更好的解决方案.

  • 我发现了这种方法,但正如你所说,它经常发射.当用户停止拖动地图并放下手指时,我只需要进行地理编码.所以我似乎也需要自己处理触摸.但新地图api中没有onTouch处理程序. (2认同)

The*_*laa 6

最简单的方法是使用 setOnCameraIdleListener 方法来处理地图片段上触摸侦听器的移动结束状态。看下面的例子:

mMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() {
    @Override
    public void onCameraMoveStarted(int i) {
        mapPin.startAnimation(animZoomOut);
    }
});

mMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() {
    @Override
    public void onCameraIdle() {
        mapPin.startAnimation(animZoomIn);
    }
});
Run Code Online (Sandbox Code Playgroud)


Tob*_*bus 5

从 play-services-maps 9.4.0 开始,您可以简单地使用GoogleMap.OnCameraMoveStartedListener,GoogleMap.OnCameraMoveListenerGoogleMap.OnCameraIdleListener

如果出于某种原因,您想使用现在已弃用的旧 API,您可以使用onCameraChangeListener. 但是你必须意识到两件事:

  1. onCameraChange() 拖动地图时可能会调用多次或仅调用一次(拖动停止时)。
  2. 最后一次调用中的相机位置onCameraChange()可能与最终的相机位置略有不同。

以下代码考虑了这两个问题:

private static final int MESSAGE_ID_SAVE_CAMERA_POSITION = 1;
private static final int MESSAGE_ID_READ_CAMERA_POSITION = 2;
private CameraPosition lastCameraPosition;
private Handler handler;
private GoogleMap googleMap;

public void onMapReady(GoogleMap theGoogleMap) {
    googleMap = theGoogleMap;

    handler = new Handler() {
        public void handleMessage(Message msg) {
            if (msg.what == MESSAGE_ID_SAVE_CAMERA_POSITION) {
                lastCameraPosition = googleMap.getCameraPosition();
            } else if (msg.what == MESSAGE_ID_READ_CAMERA_POSITION) {
                if (lastCameraPosition.equals(googleMap.getCameraPosition())) {
                    Log.d(LOG, "Camera position stable");
                }
            }
        }
    };

    googleMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {
        @Override
        public void onCameraChange(CameraPosition cameraPosition) {
            handler.removeMessages(MESSAGE_ID_SAVE_CAMERA_POSITION);
            handler.removeMessages(MESSAGE_ID_READ_CAMERA_POSITION);
            handler.sendEmptyMessageDelayed(MESSAGE_ID_SAVE_CAMERA_POSITION, 300);
            handler.sendEmptyMessageDelayed(MESSAGE_ID_READ_CAMERA_POSITION, 600);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)