2012-12-18 123 views
34

是否有一種簡單的方法可以通過Android Google Maps API v2從CameraPosition獲取可見地圖的LatLngBounds,以便我可以使用OnCameraChangeListener獲取標記的新數據。Google Maps API v2:來自CameraPosition的LatLngBounds

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

回答

27

更新自2016年八月

摘要正確現在答案這個問題是使用新onCameraIdle,而不是OnCameraChangeListener,這是現在deprecated。讀下面的話。

現在,您可以收聽「dragEnd」式的活動,甚至可以收聽最新版Android版Google地圖上的其他活動。

正如docs所示,您可避免多次的問題(又名「幾個」)的OnCameraChangeListener通過使用新的聽衆來電。例如,您現在可以查看相機移動背後的原因,這是根據要求加上fetchData問題的理想選擇。以下代碼大部分直接來自文檔。還有一件事,有必要使用Google Play Services 9.4。 2016年8月

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) 
    } 
} 

解決方法了有效的解決方案之前,由於問題的正確回答,我想上添加一個可能是下一個問題。

當使用OnCameraChangeListener從服務器獲取數據時,由於觸發此方法的頻率而出現問題。

有報道關於如何瘋狂地頻繁出現問題的例子做一個簡單的地圖時滑動,因而這種方法被觸發的issue,它會引發fetchData多個連續的時間非常的小相機的變化,即使沒有攝像頭的變化,是的,碰巧相機邊界沒有改變,但方法被觸發。

這可以在服務器端性能的影響,並會被從服務器獲取數據連續數十倍浪費了大量的設備的資源。

您可以在該鏈接中找到此問題的解決方法,但尚未有官方的方式來執行此操作,例如,使用期望的dragEndcameraChangeEnd回調。

一個例子波紋管的基礎上,從那裏的人,是我如何通過與呼叫的時間間隔玩,放棄與同一邊界的調用避免上述問題。

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

非常好! 這可能爲我節省了幾個小時的工作理解,然後解決這個問題。 謝謝! – EZDsIt

+0

@EZDsIt歡迎您! – Eduardo

+0

你還應該檢查'null'字段'currentCameraBounds'。 –

74

您無法從CameraPosition獲取LatLngBounds,但您可以從GoogleMap輕鬆獲取它們。

private GoogleMap mMap; 

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

我想知道他們爲什麼這樣設置它。可見區域不應該與地圖投影有任何關係。 – capdragon

+4

@capdragon等等,什麼?地圖投影恰好定義了定義可見區域的4個座標 – h4lc0n

+1

我想我說的是他們不應該像那樣耦合。不管投影是EPSG:4326還是EPSG:900913,無論投影是經緯度座標還是米x/y,視圖都是相同的。所以應該可以獨立執行'mMap.getProjection()'或'mMap.getVisibleRegion()'。 – capdragon