2012-12-18 20 views
34

Gibt es einen einfachen Weg, um die LatLngBounds der sichtbaren Karte von einem CameraPosition mit Android Google Maps API v2 zu bekommen, so dass ich die OnCameraChangeListener verwenden kann, um neue Daten für die Marker zu holen.Google Maps API v2: LatLngBounds von CameraPosition

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

Antwort

27

-Update seit 2016 August

Zusammenfassung die richtige Antwort jetzt dieses Problem die neuen onCameraIdle, statt OnCameraChangeListener, die jetzt deprecated zu bedienen ist. Lesen Sie weiter wie.

Jetzt können Sie Ereignisse wie "dragEnd" und sogar andere Ereignisse auf der neuesten Version von Google Maps für Android hören.

Wie in der docs gezeigt, können Sie das Problem von mehreren (auch bekannt als „mehrere“) Anrufe des OnCameraChangeListener durch die Verwendung der neuen Hörer vermeiden. Zum Beispiel können Sie jetzt überprüfen, was der Grund für die Kamerabewegung ist, was ideal ist, um mit einem fetchData Problem wie gewünscht zu koppeln. Der folgende Code stammt größtenteils direkt aus den Dokumenten. Noch eine Sache, es ist notwendig, zu verwenden.

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

Behelfslösung für eine effiziente Lösung vor 2016 August richtig

Da die Frage beantwortet wird, würde Ich mag auf, dass auf einer wahrscheinlichen nächsten Ausgabe sein hinzuzufügen.

Das Problem tritt auf, wenn Sie OnCameraChangeListener verwenden, um Daten vom Server abzurufen, aufgrund der Häufigkeit, mit der diese Methode ausgelöst wird.

Es ein issue wie crazily häufig diese Methode trigged gemeldet ist, wenn Gleiten eine einfache Karte zu tun, also im Beispiel der Frage, wäre es fetchData mehr aufeinander folgende Zeiten für sehr kleine Kamera Veränderungen auslösen, auch für keine Kamera ändert Ja, es kommt vor, dass sich die Grenzen der Kamera nicht geändert haben, aber die Methode wird ausgelöst.

Dies könnte sich auf die Leistung auf der Serverseite auswirken und würde viele Ressourcen der Geräte verschwenden, indem Daten sequenziell vom Server mehrmals abgerufen werden.

Sie können in diesem Link Problemumgehungen für dieses Problem finden, aber es gibt noch keine offizielle Möglichkeit, dies zu tun, z. B. mit einer wünschenswerten dragEnd oder cameraChangeEnd Rückrufe.

Ein Beispiel unten, bezogen auf die, die von dort, ist, wie ich das oben genannte Problem vermeiden, indem sie mit dem Zeitintervall der Anrufe zu spielen und die Anrufe mit den gleichen Grenzen zu verwerfen.

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

Sehr gut! Das rettete mir wahrscheinlich mehrere Stunden Arbeit zu verstehen und dann dieses Problem zu lösen. Danke! – EZDsIt

+0

@EZDsSie sind herzlich willkommen! – Eduardo

+0

Sie sollten auch nach 'null' für das Feld' currentCameraBounds' suchen. –

74

Sie können nicht die LatLngBounds vom Camera bekommen, aber man kann sich leicht von der GoogleMap bekommen.

private GoogleMap mMap; 

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

Ich frage mich, warum sie es so einrichten. Der sichtbare Bereich sollte nichts mit der Kartenprojektion zu tun haben. – capdragon

+4

@capdragon Warten Sie, was?Die Kartenprojektion definiert genau die 4 Koordinaten, die den sichtbaren Bereich definieren. – h4lc0n

+1

Ich denke, was ich sage ist, dass sie nicht so gekoppelt sein sollten. Sichtbare Region ist einfach Grenzen, egal in welcher Projektion es ist. Es sollte egal sein, ob die Projektion EPSG: 4326 oder EPSG: 900913 ist, die Ansicht ist die gleiche, egal ob es in Lat/Lon Koordinaten oder Metern x/y ist. Also sollte man 'mMap.getProjection()' oder 'mMap.getVisibleRegion()' unabhängig voneinander machen können. – capdragon

Verwandte Themen