13
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Google Maps Android API のカメラ変更イベントについて

Last updated at Posted at 2017-01-28

Android 向けの Google Maps ライブラリには、カメラの変更(=位置、回転、チルトのヘ変更)時に発生するイベント GoogleMap.OnCameraChangeListener があります。

が、2016年8月のリリースで OnCameraChangeListener は非推奨になっており、代わりに4つのイベントが新たに追加されました。

This release introduces a set of new camera change listeners for camera motion start, ongoing, and end events. You can also see why the camera is moving, whether it's caused by user gestures, built-in API animations or developer-controlled movements. Below is a summary of the new listeners. For details, see the guide to camera change events. (Issue 4636)

  • The onCameraMoveStarted() callback of the OnCameraMoveStartedListener is invoked when the camera starts moving. The callback method receives a reason for the camera motion.
  • The onCameraMove() callback of the OnCameraMoveListener is invoked multiple times while the camera is moving or the user is interacting with the touch screen.
  • The OnCameraIdle() callback of the OnCameraIdleListener is invoked when the camera stops moving and the user has stopped interacting with the map.
  • The OnCameraMoveCanceled() callback of the OnCameraMoveCanceledListener is invoked when the current camera movement has been interrupted.

onCameraMoveStarted - カメラの移動が開始された時

カメラの移動が開始された直後に1回発生します。 updateCameraanimateCamera などのメソッドによるカメラ移動でも、ドラッグ、ピンチなどのジェスチャによる場合でも同様です。

onCameraMoveIdle - カメラの移動が終わった時

カメラの移動が完了した直後に1回発生します。 つまりなんらかのビューの変化が起こるときには、最後にonCameraMoveIdle が必ず1回呼ばれます。アニメーションがキャンセルされたときも、onCameraMoveIdle は呼ばれます。
非推奨となった onCameraChange と立ち位置的には同じようです。ちなみに onCameraChange が呼ばれたあとで、onCameraMoveIdle が呼ばれます。

onCameraMoveStartedonCameraMoveIdle は必ず対になるかというと、 そうでないケースが存在 します。 animateCamera による地図の移動中に、地図をドラッグして地図を移動させた場合です。これについては後述します。

onCameraMove - カメラが移動した時

カメラが移動したときに発生します。 moveCamera によるダイレクトなカメラ位置への移動では、このイベントは 発生したり、しなかったりしますanimateCamera によるアニメーション付きの移動では、アニメーション中にこのイベントが発生します。ドラッグやピンチなどのジェスチャ操作でも発生します。

onCameraMoveCanceled - アニメーションがキャンセルされた時

animateCamera などのアニメーション付きのカメラ移動が、何らかの操作によりキャンセルされたときに発生します。「何らかの操作」とは、

  • アニメーション中に stopAnimation が呼ぶ
  • アニメーション中に画面をタップやドラッグする

です。

【おまけ】 animateCamera のコールバック

animateCamera には、アニメーションの完了/中止を受信できるコールバックを指定できます。

public final void animateCamera (
    CameraUpdate update, 
    GoogleMap.CancelableCallback callback)

ケース毎のイベント発生の様子

サンプルアプリを作って、実際の操作でどのようなイベントが発生するのか、調べてみました。

updateCamera メソッドの実行

  1. onCameraMoveStarted
  2. onCameraMove ←発生しないこともある
  3. onCameraChange
  4. onCameraIdle

onCameraMove は発生することも、しないこともある ようです、その条件についてはよくわかりませんでした(位置が変わるから onCameraMove が発生する、わけでもないようです)。 onCameraChange は非推奨なので打ち消し線を入れています。

animateCamera メソッドの実行(中断なし)

  1. onCameraMoveStarted
  2. onCameraMove
  3. onCameraMove
  4. ・・・
  5. animateCamera_onFinish
  6. onCameraChange
  7. onCameraIdle

移動中に onCameraMove が複数回呼び出されます。回数はアニメーションの速度により変わります。
移動が完了すると animateCamera メソッドのコールバックに onFinish が通知され、その後、 onCameraIdle が呼び出されます。

animateCamera メソッドの実行 → stopAnimation の実行

  1. onCameraMoveStarted
  2. onCameraMove
  3. ・・・
  4. onCameraMove
  5. stopAnimation 呼び出し
  6. onCameraMoveCanceled
  7. animateCamera_onCancel
  8. onCameraChange
  9. onCameraIdle

アニメーション中に stopAnimation を呼び出すと、カメラの移動が停止し、 onCameraMoveCanceledanimateCamera_onCancel の順で中止が通知されます。その後、 onCameraIdle が呼び出されるのは完了時と変わりません。

animateCamera メソッドの実行 → 移動中にドラッグして地図を移動

  1. onCameraMoveStarted ← animateCameraによる移動開始
  2. onCameraMove
  3. ・・・
  4. onCameraMove
  5. ドラッグで地図移動
  6. onCameraMoveCanceled
  7. onCameraMoveStarted ← ドラッグによる移動開始
  8. animateCamera_onCancel
  9. onCameraMove
  10. onCameraMove
  11. ・・・
  12. ドラッグやめ
  13. onCameraChange ← animateCameraによる移動終了?
  14. onCameraMove
  15. onCameraMove
  16. onCameraChange ← ドラッグによる移動終了?
  17. onCameraIdle

地図移動中にドラッグをすると、 onCameraMoveCanceled で中断が通知され、即座に 新しいカメラの移動として onCameraMoveStarted が通知されます。 animateCamera にアニメーション中止 animateCamera_onCancel が通知されるのはその後です。

その後、ドラッグによる onCameraMove が連続して発生し、ドラッグをやめると onCameraChange が2回、onCameraIdle が最後に1回呼び出されました。

このケースでの要注意点をまとめると以下です。

  • animateCameraonCancel が通知されるよりも先に、ドラッグによる onCameraMoveStarted が通知される
  • onCameraMoveStarted は2回通知される(animateCamera 呼び出し時とドラッグ開始時)のに、 onCameraIdle は最後に1回しか通知されない。

RxJava などで複数のイベントをストリーム化する時は、どうしてもイベントの発生順序や回数を意識せざるを得ませんが、その時に問題になりそうな気がします。

非アニメーション時に stopAnimation を呼ぶ

  1. onCameraChange
  2. onCameraIdle

ただ stopAnimation を呼ぶだけでも、 onCameraChangeonCameraIdle が呼ばれます。気持ち悪いですね。

まとめ

  • 非推奨になった onCameraChange の代わりとしては onCameraIdle が使えるが、ビミョーに発生タイミングが違うようなので注意!
  • 新たに追加された onCameraMoveStarted でカメラ移動の開始、 onCameraMove で移動中のカメラを受信できる。
  • onCameraXXXX は、メソッドによるカメラ移動だけでなく、ジェスチャによるカメラ移動時にも通知が来る。 animateCamera のアニメーションの終了/中断は引数のコールバックで受信する。

【おまけ】 Google Maps SDK for iOS

姉妹ライブラリである iOS 向けの Google Maps SDK では、カメラ関連イベントは

にあります。これによると、

  • willMove
  • didChangeCameraPosition
  • idleAtCameraPosition

があります。Android 用とことなっていて悩ましいです。。。

13
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?