Androidマップv2ズームですべてのマーカーを表示


286

に10個のマーカーがありGoogleMapます。できるだけズームインして、すべてのマーカーを表示したままにしますか?以前のバージョンではこれを実現できますzoomToSpan()が、v2ではそれを行う方法がわかりません。さらに、表示する必要がある円の半径も知っています。

回答:


810

CameraUpdate(おそらく)すべてのプログラムによるマップの移動を行うには、クラスを使用する必要があります。

これを行うには、最初に次のようにすべてのマーカーの境界を計算します。

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

次に、以下のファクトリを使用して、動きの説明オブジェクトを取得しますCameraUpdateFactory

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

最後にマップを移動します。

googleMap.moveCamera(cu);

または、アニメーションが必要な場合:

googleMap.animateCamera(cu);

それで全部です :)

明確化1

ほとんどすべての移動方法では、Mapオブジェクトがレイアウトプロセスを通過する必要があります。addOnGlobalLayoutListenerコンストラクトを使用して、これが発生するのを待つことができます。詳細は、この回答と残りの回答へのコメントに記載されています。こちらを使用しaddOnGlobalLayoutListenerて、マップ範囲を設定するための完全なコードを見つけることもできます

明確化2

このメソッドを1つのマーカーのみに使用すると、マップズームが「奇妙な」ズームレベルに設定される(コメントは、特定の場所で使用可能な最大ズームレベルであると私は信じています)と述べています。私はこれが予想されると思います:

  1. LatLngBounds boundsインスタンスがありますnortheastと同等の特性をsouthwest地球の面積の部分はこれでカバーされていることを意味し、bounds正確にゼロです。(単一のマーカーには領域がないため、これは論理的です。)
  2. 渡すことboundsCameraUpdateFactory.newLatLngBoundsあなたは本質的に、このようなAズームレベルの計算要求bounds(ゼロ面積を有する)全体の地図ビューをカバーします。
  3. この計算は実際には紙の上で実行できます。答えである理論上のズームレベルは+∞(正の無限大)です。実際にはMapオブジェクトはこの値をサポートしていないため、指定された場所で許可されるより妥当な最大レベルにクランプされます。

別の言い方をすると、Mapオブジェクトは、単一の場所に対してどのズームレベルを選択すればよいかをどのようにして知ることができますか?たぶん、最適な値は20でなければなりません(特定のアドレスを表す場合)。または、おそらく11(それが町を表す場合)。または多分6(それが国を表す場合)。APIはそれほど賢くなく、決定はあなた次第です。

そのmarkersため、場所が1つしかないかどうかを確認し、場所がある場合は次のいずれかを使用します。

  • CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition()) -マーカーの位置に移動し、現在のズームレベルをそのままにします。
  • CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F) -マーカーの位置に移動し、ズームレベルを任意に選択した値12に設定します。

21
onCreate呼び出しから移動を行うことはできず、ビューを作成する必要があることに注意してください。適切なサンプルを取得するには、addOnGlobalLayoutListenerを使用する必要がありました。
Baruch Even

6
@バーさて、これは部分的に本当です。正確には、一部の移動メソッドは、マップオブジェクトを作成した直後には機能しません。これは、マップオブジェクトがまだ測定れていない、つまりレイアウトプロセスが行われていないためです。典型的な修正を使用することでaddOnGlobalLayoutListener()、またはpost()適切でRunnable。これが、マーカー画面の座標を取得できない理由です-stackoverflow.com/q/14429877/1820695をonCreate参照してください。ただし、レイアウトが発生する前でも、いくつかのメソッド使用できます。4つのparamsCameraUpdateFactory.newLatLngBounds()
2013

1
男、あなたは私の日を節約しました...実際に自分でそれをしようとしていて、手動で境界を計算し、マーカーがその中にあるときにズームしていました...かなり醜く機能していましたが、単純な方法では、それは魅力のように機能します。ありがとう
Bibu

9
googleMap .setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback(){@Override public void onMapLoaded(){googleMap.moveCamera(cu);}}); これにより、測定時のエラーが回避されます。
Ramz 14

1
それ以外の場合は機能しますが、マップ上にマーカーが1つある場合、マップが不鮮明になる奇妙なレベルにズームします。これを修正するには?
Utsav Gupta 14

124

GoogleマップV2

次のソリューションは、Android Marshmallow 6(API 23、API 24、API 25、API 26、API 27、API 28)で機能します。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);

7
見栄えの良いパディングをするには、幅ではなく高さを使用し、その10%ではなく20%を使用します。
noob 2017

2
回答を受け入れると、変なズームが発生することがあります。これは魅力のように機能します。これはより良い答えです。
フセインヒヨドリ

1
この答えは受け入れられたものよりもうまく機能します。受け入れられたものはいくつかの奇妙な動作を引き起こします。
ヘイサム

13

そう

適切なサンプルを取得するには、addOnGlobalLayoutListenerを使用する必要がありました

たとえば、Googleマップは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
        }
    });

1
Udemyチュートリアルから来た、素晴らしい仕事人、彼らはあなたの答えを使って問題を解決しました。
Shantanu Shady

13

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

この一つは、それはまだ私のニーズにカメラを移動する前に、/最初のデフォルトの領域をズームマップが示された私のためにそう、長いOnGlobalLayoutListenerより道を取る
ティル

2つのマーカーがマップの境界で触れられているときにパディングを与える方法。
Pratik Butani

9

私にとってはうまくいきます。

このコードから、マップ画面に特定のズームで複数のマーカーを表示しています。

//宣言された変数

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

4

-これは元の質問に対する解決策ではありません。これは、上記のサブ問題の1つの解決策です。です。

@andrの説明2の解決策 -

境界にマーカーが1つしかないため、ズームレベルが非常に高いレベル(レベル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));

このようにすると、@ andrによって非常に適切に説明される「奇妙な」ズームレベルの問題が発生しなくなります。


良い解決策ですが、「cu」オブジェクトをonMapReady()内に配置すると、この場合は誤動作が発生します。受信された位置->ズームが大きいため、16に設定します->ユーザーがズームインします->再び受信された位置とカメラはレベル16に戻す。これは、レベル16に戻っておこうとして場所をほぼリアルタイムで受信される問題になる可能性があります
マーナビル

「そして、Googleは、この時点での最大ズームレベルを設定する方法を提供していません。」 -真の未:developers.google.com/android/reference/com/google/android/gms/...
user1209216

3

これは.. google 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));
                }
            });
        }
    }

明確な情報については、このURLをご覧ください。 https://github.com/googlemaps/android-samples/blob/master/ApiDemos/app/src/main/java/com/example/mapdemo/MarkerDemoActivity.java



1

Googleマップですべてのマーカーを表示

これらのメソッドでは、すべてのマーカーを保存し、自動的にズームしてすべてのマーカーをGoogleマップに表示します。

// Declare the Markers List.
List<MarkerOptions> markerList;
private BitmapDescriptor vnrPoint,banPoint;


public void storeAllMarkers()
{
      markerList=new ArrayList<>();
      markerList.removeAll(markerList);


      // latitude and longitude of Virudhunagar

      double latitude1=9.587209;
      double longitude1=77.951431;
   vnrPoint=BitmapDescriptorFactory.fromResource(R.drawable.location_icon_1);
      LatLng vnr = new LatLng(latitude1, longitude1);
      MarkerOptions vnrMarker = new MarkerOptions();
      vnrMarker.position(vnr);
      vnrMarker.icon(vnrPoint);
      markerList.add(vnrMarker);

      // latitude and longitude of Bengaluru

      double latitude2=12.972442;
      double longitude2=77.580643;

    banPoint=BitmapDescriptorFactory.fromResource(R.drawable.location_icon_2);

      LatLng ban = new LatLng(latitude2, longitude2);
      MarkerOptions bengalureMarker = new MarkerOptions();
      bengalureMarker.position(ban);
      bengalureMarker.icon(banPoint);
      markerList.add(bengalureMarker);

      // You can add any numbers of MarkerOptions like this.

     showAllMarkers();

 }


public void showAllMarkers()
{
    LatLngBounds.Builder builder = new LatLngBounds.Builder();

    for (MarkerOptions m : markerList) {
        builder.include(m.getPosition());
    }

    LatLngBounds bounds = builder.build();

    int width = getResources().getDisplayMetrics().widthPixels;
    int height = getResources().getDisplayMetrics().heightPixels;
    int padding = (int) (width * 0.30); 

    // Zoom and animate the google map to show all markers

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

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

0

これと同じことを完璧に行うには、もう1つの方法があります。したがって、画面上にすべてのマーカーを表示するための背後にあるアイデアには、中央緯度とズームレベルが必要です。これは、両方を提供し、すべてのマーカーの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オブジェクトを返します

ペアのペア= getCenterWithZoomLevel(l1、l2、l3 ..); mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(pair.first、pair.second));

マーカーを画面の境界から遠ざけるためにパディングを使用する代わりに、ズームを-1調整できます。


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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.