2012-12-18 7 views
34

Có cách đơn giản để lấy LatLngBounds của bản đồ hiển thị từ CameraPosition với API Google Maps Android v2 để tôi có thể sử dụng OnCameraChangeListener để tìm nạp dữ liệu mới cho các điểm đánh dấu.API Google Maps v2: LatLngBounds từ CameraPosition

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

Trả lời

27

Cập nhật kể từ tháng 8 năm 2016

Tóm tắt các đúng câu trả lời ngay bây giờ cho vấn đề này là sử dụng mới onCameraIdle, thay vì OnCameraChangeListener, mà bây giờ deprecated. Đọc dưới đây làm thế nào.

Giờ đây, bạn có thể nghe "dragEnd" giống như sự kiện và thậm chí cả các sự kiện khác trên phiên bản Google Maps dành cho Android mới nhất.

Như được hiển thị trong docs, bạn có thể tránh sự cố nhiều cuộc gọi (một số ") của số OnCameraChangeListener bằng cách sử dụng trình nghe mới. Ví dụ: bạn hiện có thể kiểm tra lý do đằng sau sự di chuyển của camera là lý tưởng để ghép nối với sự cố fetchData theo yêu cầu. Mã sau đây chủ yếu được lấy trực tiếp từ tài liệu. Một điều nữa, nó là cần thiết để sử dụng 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) 
    } 
} 

Giải pháp cho một giải pháp hiệu quả trước tháng 8 năm 2016

Như câu hỏi được trả lời đúng, tôi muốn thêm vào đó một khả năng là vấn đề tiếp theo.

Sự cố phát sinh khi sử dụng OnCameraChangeListener để tìm nạp dữ liệu từ máy chủ do tần suất mà phương pháp này được kích hoạt.

Có một issue báo cáo về cách điên cuồng thường xuyên phương pháp này được trigged khi thực hiện một bản đồ đơn giản trượt, do đó trong ví dụ của câu hỏi, nó sẽ kích hoạt fetchData nhiều lần liên tục thay đổi camera rất ít, thậm chí không có thay đổi camera , có, nó xảy ra rằng giới hạn máy ảnh đã không thay đổi, nhưng phương pháp được kích hoạt.

Điều này có thể ảnh hưởng đến hiệu suất bên máy chủ và sẽ lãng phí nhiều tài nguyên của thiết bị bằng cách tìm nạp dữ liệu tuần tự từ máy chủ.

Bạn có thể tìm thấy giải pháp liên kết đó cho vấn đề này, nhưng vẫn chưa có cách chính thức để thực hiện, ví dụ: sử dụng số gọi lại dragEnd hoặc cameraChangeEnd mong muốn.

Một ví dụ dưới đây, dựa trên những điều từ đó, là cách tôi tránh được vấn đề nói trên bằng cách chơi với khoảng thời gian của cuộc gọi và loại bỏ các cuộc gọi có cùng ranh giới.

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

} 
+0

Rất tốt! Điều đó có thể giúp tôi tiết kiệm nhiều giờ làm việc và sau đó giải quyết vấn đề này. Cảm ơn! – EZDsIt

+0

@EZDsIt bạn được chào đón! – Eduardo

+0

Bạn cũng nên kiểm tra 'null' cho trường' currentCameraBounds'. –

74

Bạn không thể tải LatLngBounds từ CameraPosition, nhưng bạn có thể lấy chúng dễ dàng từ GoogleMap.

private GoogleMap mMap; 

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

Tôi tự hỏi tại sao họ thiết lập như vậy. Vùng hiển thị không được liên quan gì đến phép chiếu bản đồ. – capdragon

+4

@capdragon Chờ đã, cái gì?Phép chiếu bản đồ chính xác là những gì xác định 4 tọa độ xác định vùng hiển thị – h4lc0n

+1

Tôi đoán những gì tôi đang nói là chúng không nên được ghép nối như thế. Nó không quan trọng nếu chiếu là EPSG: 4326 hoặc EPSG: 900913, xem là như nhau bất kể nếu nó ở tọa độ lat/lon hoặc mét x/y. Vì vậy, người ta có thể làm 'mMap.getProjection()' hoặc 'mMap.getVisibleRegion()' độc lập với nhau. – capdragon