Подтвердить что ты не робот

API Карт Google v2: LatLngBounds от CameraPosition

Есть ли простой способ получить LatLngBounds видимой карты от CameraPosition с Android Google Maps API v2, чтобы я мог использовать OnCameraChangeListener для получения новых данных для маркеров.

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

Ответ 1

Обновление с августа 2016 года

Резюме правильный ответ теперь для этой проблемы заключается в использовании нового onCameraIdle вместо OnCameraChangeListener, который теперь устарел. Прочтите ниже.

Теперь вы можете прослушивать событие "dragEnd" и даже другие события в новейшей версии Google Maps для Android.

Как показано в документах, вы можете избежать проблемы с несколькими (ака "несколькими" ) вызовами OnCameraChangeListener с помощью новых слушателей. Например, теперь вы можете проверить, в чем причина перемещения камеры, что идеально подходит для связи с проблемой fetchData по запросу. Следующий код в основном непосредственно берется из документов. Кроме того, необходимо использовать Google Play Services 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 года

Как правильно ответить на вопрос, я хотел бы добавить, что это будет следующая проблема.

Проблема возникает при использовании OnCameraChangeListener для извлечения данных с сервера из-за частоты, в которой этот метод запускается.

Существует issue, в котором сообщается о том, насколько невероятно часто этот метод срабатывает при выполнении простого перемещения карты, поэтому в примере вопроса он будет запускать fetchData несколько последовательных времен для очень маленьких изменений камеры, даже без изменений камеры, да, бывает, что границы камеры не изменились, но метод активируется.

Это может повлиять на производительность на стороне сервера и будет тратить много ресурсов на устройства, получая данные последовательно в десятки раз с сервера.

В этой связи вы можете найти обходные пути этой ссылки, но пока еще нет официального способа сделать это, например, используя желательные обратные вызовы dragEnd или cameraChangeEnd.

Один пример ниже, основанный на тех, что оттуда, заключается в том, как я избегаю вышеупомянутой проблемы, играя с интервалом времени вызовов и отбрасывая вызовы с теми же границами.

// 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;

}

Ответ 2

Вы не можете получить LatLngBounds из CameraPosition, но вы можете легко получить их из GoogleMap.

private GoogleMap mMap;

mMap.setOnCameraChangeListener(new OnCameraChangeListener() {
            @Override
            public void onCameraChange(CameraPosition position) {
                LatLngBounds bounds = mMap.getProjection().getVisibleRegion().latLngBounds;
                fetchData(bounds);
            }
        });