2013-01-31 10 views
13

Ich bin den neuen Android-Karten V2 mit diesem Layout mit:Android Karten V2 newLatLngBounds mit Lager

<fragment xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:map="http://schemas.android.com/apk/res-auto" 
    android:id="@+id/map" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    class="com.google.android.gms.maps.SupportMapFragment" 
    map:cameraBearing="270"/> 

Ich versuche, die Methode newLatLngBounds (LatLngBounds Grenzen, int padding) zum Zoomen und zu sehen, alle zu verwenden, meine Markierungen in der Karte, aber die Kamera Lager auf 0

die Beschreibung auf google-Entwickler-Dokumentation festgelegt ist, sagt:

public static Camera newLatLngBounds (LatLngBounds Grenzen, int Polsterung) (...). Der zurückCamera ein Lager von 0 und eine Neigung von 0 (...)“.

Wie kann ich den Lagerwert zu ändern?

ich ein neues Lager programmatisch nach dem einzustellen versuchte Aufruf von newLatLngBounds, etwa so:

mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100)); 
mMap.moveCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder() 
.target(mMap.getCameraPosition().target) 
.zoom(mMap.getCameraPosition().zoom) 
.bearing(270) 
.build())); 

Aber wenn ich dies einige Markierungen zeigen nicht bis

+0

Haben Sie das gelöst? –

+0

@ Mike-Bell Nein, habe ich nicht. Ich denke, das ist mit der aktuellen Android-Kartenbibliothek nicht möglich. – pedroca

Antwort

-3

schlechte Frage auf CameraUpdateFactory Google . Ich löste es mit der Zeit, winzige Zeitspanne!

public void zoomToBounds() { 
    LatLngBounds latLngBounds = getBoundsOfInput(inputPoints); 
    final int PADDING = 20; 

    final CameraPosition now = map.getCameraPosition(); 
    final float tilt = map.getCameraPosition().tilt; 
    final float bearing = map.getCameraPosition().bearing; 
    final LatLng[] target = new LatLng[1]; 
    final float[] zoom = new float[1]; 

    map.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, PADDING), 1, null); 

    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      target[0] = map.getCameraPosition().target; 
      zoom[0] = map.getCameraPosition().zoom; 
     } 
    }, 10); 
    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      map.animateCamera(CameraUpdateFactory.newCameraPosition(now), 1, null); 
     } 
    }, 30); 

    new Handler().postDelayed(new Runnable() { 
     @Override 
     public void run() { 
      map.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(target[0], zoom[0], tilt, bearing))); 
     } 
    }, 60); 
} 

schmutzig aussieht, funktioniert aber

3 Handler die Arbeit tun, jede postdelay als die größer sein muss, bevor

+0

mit Zeitspannen ist keine gute Idee, Rotation und externe Ereignisse können zu unvorhergesehenen Verhaltensweisen führen –

11

ich eine Alternative habe, hatte ich das gleiche Problem. Was ich zeigen werde ist, wie man eine Grenze in einen Zoom umwandelt, und dann verwenden wir einfach eine CameraPosition.builder(), um die richtige Position zu erstellen.

private static final double LN2 = 0.6931471805599453; 
    private static final int WORLD_PX_HEIGHT = 256; 
    private static final int WORLD_PX_WIDTH = 256; 
    private static final int ZOOM_MAX = 21; 

    public int getBoundsZoomLevel(LatLngBounds bounds, int mapWidthPx, int mapHeightPx){ 

     LatLng ne = bounds.northeast; 
     LatLng sw = bounds.southwest; 

     double latFraction = (latRad(ne.latitude) - latRad(sw.latitude))/Math.PI; 

     double lngDiff = ne.longitude - sw.longitude; 
     double lngFraction = ((lngDiff < 0) ? (lngDiff + 360) : lngDiff)/360; 

     double latZoom = zoom(mapHeightPx, WORLD_PX_HEIGHT, latFraction); 
     double lngZoom = zoom(mapWidthPx, WORLD_PX_WIDTH, lngFraction); 

     int result = Math.min((int)latZoom, (int)lngZoom); 
     return Math.min(result, ZOOM_MAX); 
    } 

    private double latRad(double lat) { 
     double sin = Math.sin(lat * Math.PI/180); 
     double radX2 = Math.log((1 + sin)/(1 - sin))/2; 
     return Math.max(Math.min(radX2, Math.PI), -Math.PI)/2; 
    } 
    private double zoom(int mapPx, int worldPx, double fraction) { 
     return Math.floor(Math.log(mapPx/worldPx/fraction)/LN2); 
    } 

Dann können Sie diesen Code verwenden und ein Lager hinzufügen/und oder mit den Grenzen kippen:

  LatLngBounds bounds = LatLngBounds.builder() 
        .include(swCorner) 
        .include(neCorner).build(); 
      CameraPosition cp = new CameraPosition.Builder() 
        .bearing(randomBearing()) 
        .tilt(randomTilt()) 
        .target(latLng) 
        .zoom(getBoundsZoomLevel(bounds, findViewById(R.id.map).getMeasuredWidth(), findViewById(R.id.map).getMeasuredHeight())) 
        .build(); 
      CameraUpdate cu = CameraUpdateFactory.newCameraPosition(cp); 
      mMap.animateCamera(cu); 

Dies funktioniert (Sie werden MMAP auf Ihre tatsächlich Karte Variable ändern müssen und die ID zu Ihrer Karten-ID).

Viel Glück! Ich habe das boundZoomLevel vom Beitrag: How do I determine the zoom level of a LatLngBounds before using map.fitBounds? Gehen Sie wie diese Antwort auch, wenn Sie Zeit haben!

+1

Das ist großartig; Vielen Dank! Aber ich frage mich zwei Dinge. Ich denke, dass die WORLD_PX-Konstanten tatsächlich 256 dpi sind, während die Ansichtsdimensionen als px zurückverfolgt werden, was zu einer falschen Skalierung führen könnte. Auch nach der Drehung können die Ecken der Grenzen von der Karte gedreht werden. Im Idealfall sollte die Koordinatenrotation vor dem Bestimmen der Grenzen stattfinden. (Und ich bin mir nicht sicher, ob der Math.floor benötigt wird oder nützlich ist.) –

+2

Peter ist richtig, WORLD PX muss für die Dichte korrigiert werden => (int) (GLOBE_WIDTH * context.getResources(). GetDisplayMetrics(). Dichte) – Jordy

+1

Dies ist die Arbeitslösung für das Problem! – miv

4

ja du kannst! nur verwenden: https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap#animateCamera(com.google.android.gms.maps.CameraUpdate, int, com.google.android.gms.maps.GoogleMap.CancelableCallback)

und CancelableCallback und in der OnFinish() Methode setzen implementieren: https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.CancelableCallback#onFinish()

den Code zu ändern das Lager. Natürlich werden Sie nicht eine einzige Animation, sondern eine Kette von zwei bekommen, aber es wird funktionieren!

mMap.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 100)/*,DURATION_IN_MS_IF_NEEDED*/,new GoogleMap.CancelableCallback(){ 
    @Override 
    public void onCancel() { 
     //DO SOMETHING HERE IF YOU WANT TO REACT TO A USER TOUCH WHILE ANIMATING 
    } 
    @Override 
    public void onFinish() { 
     mMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition.Builder() 
/*.target(mMap.getCameraPosition().target) 
.zoom(mMap.getCameraPosition().zoom)*/ 
.bearing(270) 
.build())); 
    } 
}); 

Ich glaube nicht, dass Sie Ziel und zoomen müssen, erhielt ich sie auf Kommentar, da sie von der vorherigen Animation

EDIT Blick besser auf die API verwaltet werden soll, ich habe eine Methode, die funktionieren könnte (ich kann es jetzt nicht testen, bitte sehen Sie es sich an: mit einem LatLngBounds können Sie bekommen, was ist die Zoomstufe, die am besten für den Bereich passt (es hängt von den Abmessungen des Geräts, also Sie haben) um Ansichtsdimensionen zur Laufzeit zu erhalten), und dann, wenn Sie den Zoom haben (Sie haben auch die Mitte der LatLngBounds) Sie können ein Kamera-Update mit einer einzigartigen Animation durchführen: https://developers.google.com/android/reference/com/google/android/gms/maps/model/CameraPosition, der Konstruktor erlaubt die Menge der Werte, oder Sie können den Builder wie zuvor gesehen verwenden.

Sie können online verschiedene Wege finden, dass zu tun, zum Beispiel (online nur eine schnelle Suche eine JavaScript-Version https://stackoverflow.com/a/13274361/4120431 erhalten)

Hope this können Sie mit Ihrem Problem helfen!

+1

Der springende Punkt dieser Frage ist, eine einzelne Kartenanimation zu erstellen, die beide Dinge tut – Nima

+0

es tut beide Dinge verkettet. Es gibt keinen anderen Weg, es gleichzeitig zu tun! –

+0

Auch ich muss alle Markierungen sehen, deshalb verwende ich newLatLngBound(). Wenn ich die Peilung ändere und nicht zoome, werden einige Marker nach dieser Animation ausgeblendet. – pedroca