地図の中心が変更されたらすぐに住所をジオコーディングしたい。
新しい Google マップ for Android V2 で地図の移動を処理するにはどうすればよいですか? (私は、ユーザーが指でマップをドラッグする場合について話している)
地図の中心が変更されたらすぐに住所をジオコーディングしたい。
新しい Google マップ for Android V2 で地図の移動を処理するにはどうすればよいですか? (私は、ユーザーが指でマップをドラッグする場合について話している)
新しいマップ 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();
}
ドラッグ開始イベントとドラッグ終了イベントを決定するための可能な回避策を次に示します。
SupportMapFragment または MapFragment を拡張する必要があります。onCreateView では、カスタマイズされた FrameLayout で MapView をラップする必要があります (以下の例では、「TouchableWrapper」クラスです)。これにより、タッチ イベントをインターセプトし、マップがタップされたかどうかを認識します。「onCameraChange」が呼び出された場合は、マップ ビューが押されているかどうかを確認します (以下の例では、変数「mMapIsTouched」です)。
コード例:
更新 1:
カスタマイズされたフレームレイアウト:
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);
}
}
カスタマイズした 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;
}
カメラ変更のコールバック メソッドで:
private final OnCameraChangeListener mOnCameraChangeListener =
new OnCameraChangeListener() {
@Override
public void onCameraChange(CameraPosition cameraPosition) {
if (!mMapIsTouched) {
refreshClustering(false);
}
}
};
onCameraChangeListenerを試してみます。リスナーは、カメラの移動が終了するたびに呼び出されます。リスナーは、新しい場所も提供します。私のテストでは、リスナーはドラッグ中にかなり頻繁に呼び出されましたが、より良い解決策があるかもしれません。
play-services-maps 9.4.0 以降ではGoogleMap.OnCameraMoveStartedListener
、 、 、GoogleMap.OnCameraMoveListener
およびを簡単に使用できますGoogleMap.OnCameraIdleListener
。
何らかの理由で、現在非推奨となっている古い API を使用したい場合は、 を使用できますonCameraChangeListener
。ただし、次の 2 つの点に注意する必要があります。
onCameraChange()
マップをドラッグしている間、または 1 回だけ (ドラッグが停止したとき) に何度も呼び出される可能性があります。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);
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event, MapView mapView){
if(event.getAction() == MotionEvent.ACTION_MOVE)
return true;
return false;
}
Tobus の回答に基づく、Xamarin Android の Handler 内部クラスを使用した拡張ソリューション:
public void OnMapReady(GoogleMap googleMap)
{
_googleMap = googleMap;
if (_googleMap != null)
{
_cameraPositionHandler = new CameraPositionlHandler(_googleMap);
_googleMap.CameraChange += OnCameraChanged;
}
}
void OnCameraChanged (object sender, GoogleMap.CameraChangeEventArgs e)
{
_cameraPositionHandler.RemoveMessages(MESSAGE_ID_SAVE_CAMERA_POSITION);
_cameraPositionHandler.RemoveMessages(MESSAGE_ID_READ_CAMERA_POSITION);
_cameraPositionHandler.SendEmptyMessageDelayed(MESSAGE_ID_SAVE_CAMERA_POSITION, 300);
_cameraPositionHandler.SendEmptyMessageDelayed(MESSAGE_ID_READ_CAMERA_POSITION, 600);
}
次の内部クラスを使用:
private class CameraPositionlHandler : Handler
{
private CameraPosition _lastCameraPosition;
private GoogleMap _googleMap;
public CameraPositionlHandler (GoogleMap googleMap)
{
_googleMap = googleMap;
}
public override void HandleMessage(Message msg)
{
if (_googleMap != null)
{
if (msg.What == MESSAGE_ID_SAVE_CAMERA_POSITION) {
_lastCameraPosition = _googleMap.CameraPosition;
} else if (msg.What == MESSAGE_ID_READ_CAMERA_POSITION) {
if (_lastCameraPosition.Equals(_googleMap.CameraPosition)) {
Console.WriteLine("Camera position stable");
//do what you want
}
}
}
}
}
マップ内のイベント onclick はmap.setOnMapClick ...だと思いますが、イベント ドラッグはmap.onCameraChangeListenerです。これは、両方の関数でlog.eを呼び出し、onClick view とonDrag view のように表示されるためです。だからあなたのためにそれらを使うだけです。