41

を使用してマーカーの新しいデータを取得できるように、Android Google Maps API v2 を使用しLatLngBoundsて可視マップを取得する簡単な方法はありますか。CameraPositionOnCameraChangeListener

mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition position) {
                LatLngBounds bounds = ?;
                fetchNewData(bounds);
            }
        });
4

2 に答える 2

78

CameraPosition から LatLngBounds を取得することはできませんが、GoogleMap から簡単に取得できます。

private GoogleMap mMap;

mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition position) {
                LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
                fetchData(bounds);
            }
        });
于 2012-12-18T21:50:55.907 に答える
41

2016 年 8 月以降の更新

要約すると、この問題に対する現在の正解は、非推奨になったonCameraIdleの代わりに新しい を使用することです。以下の方法をお読みください。OnCameraChangeListener

これで、「dragEnd」のようなイベントや、最新バージョンの Android 用 Google マップのその他のイベントを聞くことができます。

docsに示されているように、新しいリスナーを使用することで、 の複数 (別名「複数」) の呼び出しの問題を回避できます。OnCameraChangeListenerたとえば、カメラの動きの背後にある理由を確認できるようになりました。これは、fetchData要求に応じて問題と組み合わせるのに理想的です。次のコードは、主にドキュメントから直接取得したものです。もう1つ、 Google Play サービス 9.4を使用する必要があります。

public class MyCameraActivity extends FragmentActivity implements
        OnCameraMoveStartedListener,
        OnCameraMoveListener,
        OnCameraMoveCanceledListener,
        OnCameraIdleListener,
        OnMapReadyCallback {

    private GoogleMap mMap;

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

        SupportMapFragment mapFragment =
            (SupportMapFragment) getSupportFragmentManager()
                    .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);
    }

    @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. Fetch the data from the server!", Toast.LENGTH_SHORT).show();
        LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
        fetchData(bounds)
    }
}

2016 年 8 月より前の効率的なソリューションの回避策

質問は適切に回答されているので、次の問題に追加したいと思います。

OnCameraChangeListenerこのメソッドがトリガーされる頻度が原因で、を使用してサーバーからデータをフェッチするときに問題が発生します。

単純なマップのスライドを行うときにこのメソッドが非常に頻繁にトリガーされるという問題fetchDataが報告されているため、質問の例では、カメラの変更がない場合でも、カメラの変更がほとんどない場合でも、複数の連続した時間をトリガーします。カメラの境界は変更されていませんが、メソッドはトリガーされます。

これは、サーバー側のパフォーマンスに影響を与える可能性があり、サーバーからデータを何十回も連続して取得することで、多くのデバイスのリソースを浪費する可能性があります。

そのリンクでこの問題の回避策を見つけることができますが、それを行う公式の方法はまだありません。たとえば、desirabledragEndcameraChangeEndcallbacks を使用します。

そこからの例に基づいて、呼び出しの時間間隔を調整し、同じ境界を持つ呼び出しを破棄することで、前述の問題を回避する方法を以下に示します。

// Keep the current camera bounds
private LatLngBounds currentCameraBounds;

new GoogleMap.OnCameraChangeListener() {
    private static int CAMERA_MOVE_REACT_THRESHOLD_MS = 500;
    private long lastCallMs = Long.MIN_VALUE;

    @Override
    public void onCameraChange(CameraPosition cameraPosition) {
      LatLngBounds bounds = map.getProjection().getVisibleRegion().latLngBounds;
      // Check whether the camera changes report the same boundaries (?!), yes, it happens
      if (currentCameraBounds.northeast.latitude == bounds.northeast.latitude
         && currentCameraBounds.northeast.longitude == bounds.northeast.longitude
         && currentCameraBounds.southwest.latitude == bounds.southwest.latitude
         && currentCameraBounds.southwest.longitude == bounds.southwest.longitude) {
         return;
       }

      final long snap = System.currentTimeMillis();
      if (lastCallMs + CAMERA_MOVE_REACT_THRESHOLD_MS > snap) {
        lastCallMs = snap;
        return;
      }

      fetchData(bounds);

      lastCallMs = snap;
      currentCameraBounds = bounds;

}
于 2015-12-02T14:40:55.653 に答える