お使いのブラウザは、バージョンが古すぎます。

このサイトは、Internet Explore8・Internet Explore9には対応しておりません。
恐れ入りますが、お使いのブラウザをバージョンアップしていただきますよう宜しくお願いいたします。

MapFragmentのスクロールを検知する

お久しぶりです。pencoです。
 
今回はMapFragmentを使用してアプリ内に設置したGoogleMapがスクロールされたことを検知したいと思います。
最終的にやりたい事としては、Mapに表示したマーカーをタップしたらMap下部にViewを表示し、MapがスクロールされたらViewを非表示にする、ということをしたいと思います。
 

完成予想

device-2015-04-06-190132 device-2015-04-06-190153

このやり方が正しいかは分かりませんので、あしからずです。
 
 
ちなみにGoogleMapのアプリへの表示方法は長くなるので割愛します。
導入についてはこちらのサイト様が ↓↓
Google Maps Android API v2でアプリケーション開発
 
GoogleMapの操作についてはこちらのサイト様が ↓↓
マーカーを表示する
Google Maps Android API v2 逆引きリファレンス 分かりやすいと思います。
 
ただし、GoogleMapインスタンスの取得方法が変わり、getMap() メソッドは非推奨となったようです。
Google Play 開発者サービス 6.5 のご紹介
Google Maps Android API v2
 
上記サイトにもありますが、MapFragment.getMapAsync()メソッドを使用するようにとありますので、以下の様に修正します。

public class MainActivity extends ActionBarActivity{
    GoogleMap map;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom_map);

        //MapFragment.getMap()メソッドは非推奨になったため、getMapAsync()を使う
        SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap map) {
        this.map = map;
        map.setMyLocationEnabled(true);// 現在位置ボタンの表示
        setMarker();
    }

    private void setMarker(){
        //マーカーを追加
        LatLng markerPos = new LatLng(35.646587, 139.653114);
        MarkerOptions options = new MarkerOptions();
        options.position(markerPos);
        map.addMarker(options);
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(markerPos, 15));      
    }
}

これで、この様に表示できるかと思います。
device-2015-04-06-191535
 
では本題のMapのスクロールの検知に入ります。
公式のリファレンスを見ると、GoogleMap.OnCameraChangeListener が使えそうですね。
 
onCameraChange(CameraPosition position)はカメラ位置(=表示位置)が変わった時に呼ばれるメソッドです。
これを利用して、『前回位置と今回位置が一致しなければスクロールした』と判断できそうです。

LatLng oldPos = null;
...

    @Override
    public void onMapReady(GoogleMap map) {
        this.map = map;
        map.setMyLocationEnabled(true);// 現在位置ボタンの表示
        map.setOnMarkerClickListener(this);//マーカークリック時のイベントが呼ばれる
        map.setOnCameraChangeListener(this);//カメラ位置変更のイベントが呼ばれる
        setMarker();
    }

    @Override
    public void onCameraChange(CameraPosition pos) {
        if(oldPos != null){
            LatLng newPos = pos.target;
        
            //カメラが動いたらスクロールと判定
            if(!oldPos.equals(newPos)){
                //スクロールした時の処理
            }
        }
        oldPos = pos.target;
    }

 
 
マップのスクロール検知自体はこれで問題ないのですが、マーカーがタップされた際にもonCameraChange()メソッドが呼ばれるようなので、はじめに述べた「マーカータップで表示、マップスクロールで非表示」ということをやろうとすると問題があります。
そのため、マーカーがタップされたイベントでフラグを立てて、直後のonCameraChange()はスルーするようにします。
カスタムのViewを表示するという処理を追加したコードが以下のようになります。

public class MainActivity extends ActionBarActivity{
    GoogleMap map;
    LatLng oldPos = null;
    boolean markerClickFlag = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.custom_map);

        //MapFragment.getMap()メソッドは非推奨になったため、getMapAsync()を使う
        SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @Override
    public void onMapReady(GoogleMap map) {
        this.map = map;
        map.setMyLocationEnabled(true);// 現在位置ボタンの表示
        setMarker();
    }

    private void setMarker(){
        //マーカーを追加
        LatLng markerPos = new LatLng(35.646587, 139.653114);
        MarkerOptions options = new MarkerOptions();
        options.position(markerPos);
        map.addMarker(options);
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(markerPos, 15));      
    }

    @Override
    public void onMapReady(GoogleMap map) {
        this.map = map;
        map.setMyLocationEnabled(true);// 現在位置ボタンの表示
        map.setOnMarkerClickListener(this);//マーカークリック時のイベントが呼ばれる
        map.setOnCameraChangeListener(this);//カメラ位置変更のイベントが呼ばれる
        setMarker();
    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        // マーカークリック時のイベント
        view.show();//カスタムViewを表示
        markerClickFlag = true;
        return false;
    }

    @Override
    public void onCameraChange(CameraPosition pos) {
        if(oldPos != null){
            LatLng newPos = pos.target;
        
            //カメラが動いたらスクロールと判定
            //onMarkerClick()時に発生するカメラの移動はスクロールから除外
            if(!oldPos.equals(newPos) && !markerClickFlag){
                view.hide();
            }
        }
        oldPos = pos.target;
        markerClickFlag = false;
    }
}

 
これで思う通りの動きになりました。
今回はここまで。

コメントをどうぞ

メールアドレスは公開されません。* が付いている欄は必須項目です。


お気軽にお問い合わせください。

日本VTR実験室では、お仕事のご依頼、ブログ・コラムのご感想などを受け付けております。
アプリ開発・コンテンツ制作でお困りでしたら、お気軽にご相談ください。
ご連絡お待ちしております。

お問い合わせはこちらから

03-3541-1230

info@nvtrlab.jp

電話受付対応時間:平日AM9:30〜PM6:00