220

我在GoogleMap中有10個標記。我想盡可能放大並保留所有標記?在早期版本中,這可以從zoomToSpan()實現,但在V2中,我不知道如何做到這一點。此外,我知道需要可見的圓的半徑。Android地圖v2放大以顯示所有標記

+1

我的答案會給你一個最新的Android API最簡單的解決方案。 http://stackoverflow.com/a/38013331/1348522 – 2016-11-08 10:12:47

回答

660

您應該使用CameraUpdate類(可能)執行所有程序化的地圖移動。

要做到這一點,首先計算所有標記的範圍,像這樣:CameraUpdateFactory

int padding = 0; // offset from edges of the map in pixels 
CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding); 

最後移動地圖

LatLngBounds.Builder builder = new LatLngBounds.Builder(); 
for (Marker marker : markers) { 
    builder.include(marker.getPosition()); 
} 
LatLngBounds bounds = builder.build(); 

通過使用工廠然後得到一個運動的描述對象:

googleMap.moveCamera(cu); 

或者如果你想動畫:

googleMap.animateCamera(cu); 

這是所有:)

澄清1

幾乎所有的運動方法要求已通過佈局過程中Map對象。您可以使用addOnGlobalLayoutListener構造等待發生這種情況。詳細信息可以在評論中找到這個答案和其餘的答案。您還可以找到一個complete code for setting map extent using addOnGlobalLayoutListener here

澄清2

一種意見指出,使用這種方法只有一個標記導致地圖縮放設置爲一個「奇怪的」縮放級別(這我認爲是可用於指定位置的最大縮放級別)。我認爲這是預料之中,因爲:

  1. LatLngBounds bounds實例將有northeast屬性等於southwest,這意味着本bounds覆蓋地球面積的部分正好是零。 (這是合乎邏輯的,因爲單個標記沒有區域。)
  2. 通過將bounds傳遞給CameraUpdateFactory.newLatLngBounds您基本上要求計算這樣一個縮放級別,即bounds(具有零區域)將覆蓋整個地圖視圖。
  3. 您實際上可以在一張紙上執行此計算。作爲答案的理論縮放級別是+ ∞(正無窮大)。在實踐中,Map對象不支持該值,因此它被限制爲給定位置允許的更合理的最大級別。

另一種方式把它:Map對象怎麼能知道什麼縮放級別應該是選擇一個單一位置?也許最佳值應該是20(如果它代表特定的地址)。或者也許11(如果它代表一個城鎮)。或者,也許6(如果它代表一個國家)。 API不是那麼聰明,這個決定取決於你。

所以,你應該簡單地檢查是否markers只有一個位置,如果是這樣,使用一個:

  • CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition()) - 去標記的位置,離開當前縮放級別不變。
  • CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F) - 去標記的位置,設置縮放級別任意選擇值12
+19

應該指出的是,移動不能從onCreate調用發生,視圖必須被創建。我需要使用addOnGlobalLayoutListener來獲取適當的樣本。 – 2013-08-01 17:57:42

+6

@巴爾,這部分是真的。準確地說:*一些*移動方法在創建地圖對象後不會正常工作。其原因是地圖對象尚未被測量*但尚未經過佈局處理。一個典型的解決方法是使用'addOnGlobalLayoutListener()'或'post()'和適當的'Runnable'。這正是獲取標記屏幕座標不能在'onCreate'中完成的原因 - 請參閱http://stackoverflow.com/q/14429877/1820695但是,您甚至可以在佈局發生之前使用某些方法 - 例如。 'CameraUpdateFactory.newLatLngBounds()'帶有* 4個參數*。 – andr 2013-08-01 19:18:04

+1

男人,你救了我一天...實際上是試圖自己做,手動計算邊界,並縮放標記是在它...工作相當醜陋,但用你的簡單方法,它的作品像一個魅力。謝謝 – Bibu 2014-03-08 20:40:40

11

所以

I needed to use addOnGlobalLayoutListener to get the appropriate sample

例如,您的谷歌地圖裏面的RelativeLayout:

RelativeLayout mapLayout = (RelativeLayout)findViewById(R.id.map_layout); 
mapLayout.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
      //and write code, which you can see in answer above 
     } 
    }); 
11

我無法使用onGlobalLayoutlistener,所以這裏有另一個解決方案來防止 "Map size can't be 0. Most likely, layout has not yet occured for the map view. Either wait until layout has occurred or use newLatLngBounds(LatLngBounds, int, int, int) which allows you to specify the map's dimensions."錯誤:

mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() { 
@Override 
public void onMapLoaded() { 
    mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 15)); 
} 
}); 
+0

這一個比OnGlobalLayoutListener更長的路,所以對我來說它仍然顯示首先映射默認區域/縮放,然後將攝像機移動到我需要的地方 – Till 2016-07-05 12:47:16

0

使用「getCenterCoordinate」方法獲取中心座標並在CameraPosition中使用。

private void setUpMap() { 
    mMap.setMyLocationEnabled(true); 
    mMap.getUiSettings().setScrollGesturesEnabled(true); 
    mMap.getUiSettings().setTiltGesturesEnabled(true); 
    mMap.getUiSettings().setRotateGesturesEnabled(true); 

    clientMarker = mMap.addMarker(new MarkerOptions() 
      .position(new LatLng(Double.valueOf(-12.1024174), Double.valueOf(-77.0262274))) 
      .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_taxi)) 
    ); 
    clientMarker = mMap.addMarker(new MarkerOptions() 
      .position(new LatLng(Double.valueOf(-12.1024637), Double.valueOf(-77.0242617))) 
      .icon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_location)) 
    ); 

    camPos = new CameraPosition.Builder() 
      .target(getCenterCoordinate()) 
      .zoom(17) 
      .build(); 
    camUpd3 = CameraUpdateFactory.newCameraPosition(camPos); 
    mMap.animateCamera(camUpd3); 
} 


public LatLng getCenterCoordinate(){ 
    LatLngBounds.Builder builder = new LatLngBounds.Builder(); 
    builder.include(new LatLng(Double.valueOf(-12.1024174), Double.valueOf(-77.0262274))); 
    builder.include(new LatLng(Double.valueOf(-12.1024637), Double.valueOf(-77.0242617))); 
    LatLngBounds bounds = builder.build(); 
    return bounds.getCenter(); 
} 
-2
//For adding a marker in Google map 
     MarkerOptions mp = new MarkerOptions(); 
     mp.position(new LatLng(Double.parseDouble(latitude), Double.parseDouble(longitude))); 
     mp.snippet(strAddress); 
     map.addMarker(mp); 

     try { 

      b = new LatLngBounds.Builder(); 

      if (MapDetailsList.list != null && MapDetailsList.list.size() > 0) { 

       for (int i = 0; i < MapDetailsList.list.size(); i++) { 

        b.include(new LatLng(Double.parseDouble(MapDetailsList.list.get(i).getLatitude()), 
          Double.parseDouble(MapDetailsList.list.get(i).getLongitude()))); 

       } 
       LatLngBounds bounds = b.build(); 

       DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); 
       int width = displayMetrics.widthPixels; 
       int height = displayMetrics.heightPixels; 

       // Change the padding as per needed 
       CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width-200, height-200, 5); 
       // map.setCenter(bounds.getCenter()); 

       map.animateCamera(cu); 

      } 

     } catch (Exception e) { 

     } 

http://i64.tinypic.com/2qjybh4.png

http://i63.tinypic.com/flzwus.png

http://i63.tinypic.com/112g5fm.png

2

注意 - 這不是原來的問題的解決方案。這是對above討論的子問題之一的解決方案。

解決@andr 澄清2 -

它真的有問題時,有隻有一個邊界標記,由於它的縮放級別設置爲一個非常高的水平(級21)。而Google目前沒有提供任何設置最大縮放級別的方法。這也可能發生在有多於一個標記但它們彼此非常接近時。然後也會發生同樣的問題。

解決方案 - 假設您希望您的地圖不超過16個縮放級別。然後,後做事 -

CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, padding); 
mMap.moveCamera(cu); 

檢查您的縮放級別已越過16級(或任何你想要的) -

float currentZoom = mMap.getCameraPosition().zoom; 

如果這個級別大於16,這也只會是如果有是非常少的標記或所有標記都非常接近對方,後來乾脆只塞汀縮放比例爲16

mMap.moveCamera(CameraUpdateFactory.zoomTo(16)); 

這樣,你永遠不會有在p縮小你在那個特定的位置地圖@andr也很好地解釋了「奇異」縮放級別的問題。

+0

很好的解決方案,但是如果您將「cu」對象置於MapReady()內部,那麼在這種情況下會出現一個錯誤行爲:**收到位置 - >縮放很大,它16 - >然後用戶放大 - >位置再次收到和相機被放回到級別16 **。 當幾乎實時收到位置時,這可能會成爲問題,因爲它會一直返回到第16級。 – 2017-02-01 09:32:04

+0

「Google現在不提供任何方法來設置最大縮放級別。」 - 不正確:https ://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.html#setMaxZoomPreference(float) – user1209216 2017-05-22 07:01:59

1

這會幫助..從谷歌apis演示

private List<Marker> markerList = new ArrayList<>(); 
Marker marker = mGoogleMap.addMarker(new MarkerOptions().position(geoLatLng) 
       .title(title)); 
markerList.add(marker); 
    // Pan to see all markers in view. 
    // Cannot zoom to bounds until the map has a size. 
    final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView(); 
    if (mapView!=null) { 
     if (mapView.getViewTreeObserver().isAlive()) { 
      mapView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
       @SuppressWarnings("deprecation") // We use the new method when supported 
       @SuppressLint("NewApi") // We check which build version we are using. 
       @Override 
       public void onGlobalLayout() { 
        //Calculate the markers to get their position 
        LatLngBounds.Builder b = new LatLngBounds.Builder(); 
        for (Marker m : markerList) { 
         b.include(m.getPosition()); 
        } 
        // also include current location to include in the view 
        b.include(new LatLng(mLocation.getLatitude(),mLocation.getLongitude())); 

        LatLngBounds bounds = b.build(); 
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { 
         mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
        } else { 
         mapView.getViewTreeObserver().removeOnGlobalLayoutListener(this); 
        } 
        mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50)); 
       } 
      }); 
     } 
    } 

清除信息看看這個網址。 https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java

52

谷歌地圖V2:爲Android棉花糖6(API 23,API 24,API 25),以及邊界最佳的工作解決方案中放大的MarkerOptions,工程在Xamarin還

LatLngBounds.Builder builder = new LatLngBounds.Builder(); 

//the include method will calculate the min and max bound. 
builder.include(marker1.getPosition()); 
builder.include(marker2.getPosition()); 
builder.include(marker3.getPosition()); 
builder.include(marker4.getPosition()); 

LatLngBounds bounds = builder.build(); 

int width = getResources().getDisplayMetrics().widthPixels; 
int height = getResources().getDisplayMetrics().heightPixels; 
int padding = (int) (width * 0.10); // offset from edges of the map 10% of screen 

CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, width, height, padding); 

mMap.animateCamera(cu); 
+0

謝謝你:) – 2016-10-30 09:58:41

+1

爲了更好看的填充,使用高度而不是寬度和採取20%,而不是10%。 – noob 2017-07-31 08:50:44

+0

不錯,這也適用於Xamarin! – JMK 2017-09-02 13:39:33

3

Working fine for me.

從這個代碼,我在地圖屏幕上顯示特定縮放的多個標記。

//聲明的變量

private LatLngBounds bounds; 
private LatLngBounds.Builder builder; 

//方法與繪製圖標添加多個標記點

private void drawMarker(LatLng point, String text) { 

     MarkerOptions markerOptions = new MarkerOptions(); 
     markerOptions.position(point).title(text).icon(BitmapDescriptorFactory.fromResource(R.drawable.icon)); 
     mMap.addMarker(markerOptions); 
     builder.include(markerOptions.getPosition()); 

    } 

//對於添加多個標記可見在地圖上

@Override 
    public void onMapReady(GoogleMap googleMap) { 
     mMap = googleMap; 
     builder = new LatLngBounds.Builder(); 
    for (int i = 0; i < locationList.size(); i++) { 

     drawMarker(new LatLng(Double.parseDouble(locationList.get(i).getLatitude()), Double.parseDouble(locationList.get(i).getLongitude())), locationList.get(i).getNo()); 

    } 
    bounds = builder.build(); 
    CameraUpdate cu = CameraUpdateFactory.newLatLngBounds(bounds, 0); 
    mMap.animateCamera(cu); 
0

我有類似的問題,使用下面的代碼解決了問題:

CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5)我的情況一般位置差異不超過兩個鄰居城市。

zoom to fit all markers on map google maps v2

0

我有一個其他的方式做同樣的事情完美的作品。所以後面的想法顯示屏幕上的所有標記,我們需要一箇中心拉長和縮放級別。這裏有一個函數可以讓你和所有標記的Latlng對象作爲輸入。

public Pair<LatLng, Integer> getCenterWithZoomLevel(LatLng... l) { 
    float max = 0; 

    if (l == null || l.length == 0) { 
     return null; 
    } 
    LatLngBounds.Builder b = new LatLngBounds.Builder(); 
    for (int count = 0; count < l.length; count++) { 
     if (l[count] == null) { 
      continue; 
     } 
     b.include(l[count]); 
    } 

    LatLng center = b.build().getCenter(); 

    float distance = 0; 
    for (int count = 0; count < l.length; count++) { 
     if (l[count] == null) { 
      continue; 
     } 
     distance = distance(center, l[count]); 
     if (distance > max) { 
      max = distance; 
     } 
    } 

    double scale = max/1000; 
    int zoom = ((int) (16 - Math.log(scale)/Math.log(2))); 
    return new Pair<LatLng, Integer>(center, zoom); 
} 

該函數返回對對象,您可以像使用

Pair pair = getCenterWithZoomLevel(l1,l2,l3..); mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(pair.first, pair.second));

可以代替使用填充您的標記從屏幕邊界保持距離,你可以通過調整-1變焦。

相關問題