6989


Google Maps Android API v2を使い地図アプリを作ろうと考えております。  
地図の現在の位置(v2ではカメラの位置ですが)をリアルタイムに、地図のビューが1ピクセルでも移動した瞬間を繰り返し取得するにはどうしたらよいでしょうか。

最終的に作ろうとしている物の例は以下の動画のマーカーの動きです。  
<https://www.youtube.com/watch?v=dJ8HxjqLGEs>  
<https://play.google.com/store/apps/details?id=com.walkerplus.walkertouch>  
Google Maps Android API v2においてマーカーは静止画しか設定出来ないので、この動画の様なアニメーションを行う事は出来ません。  
地図の上にビューを配置し、マーカーを自力で描画しようと思ったのですが、それには地図のビューが1pxでも更新されたタイミングに合わせて自力描画マーカーの位置を更新する必要があります。  
setOnCameraChangeListenerでカメラの位置変更を取得しようと思ったのですが、イベントが呼ばれるタイミングが1秒に数回程度であり、自力描画マーカーの位置が全く追いついていきません。

そこで、Android Google Maps SDKで地図の現在位置をリアルタイムで取得する方法を教えて欲しいです。  
タイトルから離れてしまいますが、Android Google Maps
SDKで地図の上に自作のビューを貼り付ける方法でも結構です。タイルオーバーレイという物もありますが、やはりこれも静止画が基本ですので自由なビューを貼り付けたいです。


CC BY-SA 3.0
2015-02-18T19:28:14.713
6709
2015-07-22T01:46:34.033
2015-02-22T15:50:42.950
805
805
question
android google-maps
Android Google Maps SDKで地図の現在位置をリアルタイムで取得するには


オーバレイしている`view`の`onDraw()`から、`GoogleMap#getCameraPosition()`か、[GoogleMap#getProjection()](https://developer.android.com/reference/com/google/android/gms/maps/GoogleMap.html#getProjection\(\)),
[Projection#getVisibleRegion()](https://developer.android.com/reference/com/google/android/gms/maps/Projection.html#getVisibleRegion\(\))
を呼び出して位置を取得してみてはいかがでしょうか。  
同時に、適当なスレッドからオーバレイしている`view`の`invalidate()`を呼出続ければ、`onDraw()`のほうも繰り返し呼び出されます。

マーカアイコンを大小するアニメーションを入れる、という要件に対しては、マーカが視野に入ったタイミングでマーカをremoveして新しいアイコンでputし直すしか[なさそう](https://stackoverflow.com/a/14883628)です。


CC BY-SA 3.0
2015-02-19T08:54:07.517
6763
2015-02-23T02:07:24.577
2017-05-23T12:38:55.250
-1
7572
6709
answer


私も同じような問題にあたり、強引ですがMapFragmentのViewに自作のViewを重ねる方法を使いました。

重ねたViewはOnGestureListenerをimplementしたFrameLayoutです。

私が使っているのは以下のような感じです。

試行錯誤中で要らない処理が含まれている可能性がありますが、参考になればと思います。

これで地図をドラッグしたり、フリックしたりする動きには逐一ついていきますが、例えば  
GoogleMap#animateCamera()で移動した場合などは別の処理が必要です。

[code]

    public class TouchableWrapper extends FrameLayout implements GestureDetector.OnGestureListener{
    
        protected GestureDetector gd;
        private Scroller scroller;
        private final Handler handler = new Handler();
    
        public TouchableWrapper(Context context) {
            super(context);
            scroller = new Scroller(context);
            init();
        }
    
        public void init(){
            gd = new GestureDetector(getContext(),this);
    
        }
    
        @Override
        public boolean onInterceptTouchEvent(MotionEvent ev){
            super.onInterceptTouchEvent(ev);
            gd.onTouchEvent(ev);
            return false;
        }
    
        @Override
        public boolean dispatchTouchEvent(MotionEvent ev) {
    
    
            switch (ev.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    //ここに移動の処理、座標の取得等
                    break;
    
                case MotionEvent.ACTION_MOVE:
    
                    //ここに移動の処理、座標の取得等
                    break;
    
                case MotionEvent.ACTION_UP:
                    //ここに移動の処理、座標の取得等
    
                    break;
                case MotionEvent.ACTION_CANCEL:
                   //ここに移動の処理、座標の取得等
                    break;
            }
    
            return super.dispatchTouchEvent(ev);
    
        }
    
        @Override
        public boolean onDown(MotionEvent e) {
    
            return false;
        }
    
        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
    
    
            scroller.fling(
                    (int)e2.getX(),
                    (int)e2.getY(),
                    (int)velocityX,
                    (int)velocityY,
                    0, getWidth(), 0, getHeight());
    
            handler.post(new Runnable() {
    
                @Override
                public void run() {
                    scroller.computeScrollOffset();
                    //ここに移動の処理、座標の取得等
                    invalidate();
                    if(!scroller.isFinished()){
    
                        handler.postDelayed(this, 50);
                    }
                }
            });
    
            return false;
        }
    
        @Override
        public void onLongPress(MotionEvent e) {
    
        }
    
        @Override
        public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
    
            return false;
        }
    
        @Override
        public void onShowPress(MotionEvent e) {
    
        }
    
        @Override
        public boolean onSingleTapUp(MotionEvent e) {
            return false;
        }
    }
    
[/code]

ジェスチャーについてはこちらを参考にしました。  
【Android】GestuerDetectorとScrollerを組み合わせた例 ｜ザワプロ！  
<http://zawapro.com/?p=1474>


CC BY-SA 3.0
2015-02-24T01:23:12.500
6989
2015-07-22T01:46:34.033
2015-07-22T01:46:34.033
3516
7256
6709
answer