모든 마커를 표시하는 Android Map 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구문을 사용하여이 문제가 발생할 때까지 기다릴 수 있습니다 . 자세한 내용은이 답변에 대한 의견과 나머지 답변에 나와 있습니다. here를 사용하여 맵 범위를 설정하기위한 전체 코드를addOnGlobalLayoutListener 찾을 수도 있습니다 .

설명 2

한 의견에서는이 방법을 하나의 마커에만 사용하면지도 확대 / 축소가 "기괴한"확대 / 축소 수준 (주어진 위치에서 사용 가능한 최대 확대 / 축소 수준)으로 설정됩니다. 나는 이것이 다음과 같은 이유로 예상된다고 생각한다.

  1. LatLngBounds bounds인스턴스 것이다 northeast동일한 특성 southwest이 적용 지구의 영역의 부분 즉, bounds정확히 제로이다. (단일 마커에는 면적이 없으므로 논리적입니다.)
  2. 전달하여 boundsCameraUpdateFactory.newLatLngBounds당신은 본질적으로되도록 줌 레벨의 계산 요청 bounds(제로 영역을 갖는) 전체지도보기를 다룰 것입니다.
  3. 실제로이 계산은 한 장의 종이에서 수행 할 수 있습니다. 정답 인 이론적 줌 레벨은 + ∞ (양의 무한대)입니다. 실제로 Map객체는이 값을 지원하지 않으므로 주어진 위치에 허용되는보다 합리적인 최대 수준으로 고정됩니다.

그것을 넣는 또 다른 방법 : Map객체가 단일 위치에 대해 어떤 줌 레벨을 선택 해야하는지 알 수 있습니까? 최적의 값은 20이어야합니다 (특정 주소를 나타내는 경우). 아니면 11 일 수도 있습니다 (도시를 나타내는 경우). 또는 6 (국가를 대표하는 경우). API는 현명하지 않으며 결정은 당신에게 달려 있습니다.

따라서 markers위치가 하나만 있는지 확인 하고 있으면 다음 중 하나를 사용하십시오.

  • CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition()) -마커 위치로 이동하여 현재 확대 / 축소 수준을 그대로 둡니다.
  • CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F) -마커 위치로 이동하여 줌 레벨을 임의로 선택된 값 12로 설정하십시오.

21
onCreate 호출에서 이동을 수행 할 수 없으므로보기를 작성해야합니다. 적절한 샘플을 얻으려면 addOnGlobalLayoutListener를 사용해야했습니다.
Baruch 짝수

6
@Bar 글쎄, 이것은 사실이다. 정확하게 말하면 : 일부 이동 방법은 맵 객체를 만든 직후 작동하지 않습니다. 그 이유는 맵 객체가 아직 측정 되지 않았기 때문에 레이아웃 프로세스를 거치지 않았기 때문입니다. 일반적인 수정 방법은 addOnGlobalLayoutListener()또는 post()적절한 것을 사용 하는 것 Runnable입니다. 이것이 바로 마커 화면 좌표를 얻을 수없는 이유입니다 ( stackoverflow.com/q/14429877/1820695onCreate 참조). 그러나 레이아웃이 발생하기 전에 몇 가지 방법을 사용할 있습니다. 와 4 PARAMS . CameraUpdateFactory.newLatLngBounds()
andr

1
남자, 당신은 내 하루를 절약하고 ... 실제로 내 자신의 일을하려고하고 수동으로 범위를 계산하고 마커가있는 동안 확대 / 축소하는 것은 꽤 추한 일이지만 간단한 방법으로 매력처럼 작동합니다. 감사합니다
Bibu

9
googleMap .setOnMapLoadedCallback (new GoogleMap.OnMapLoadedCallback () {@ void public void onMapLoaded () {googleMap.moveCamera (cu);}}); 이것은 측정 오류를 피할 것입니다.
Ramz

1
그렇지 않으면 작동하지만지도에 단일 마커가 있으면지도가 흐려지는 기괴한 수준으로 확대됩니다. 이 문제를 해결하는 방법?
Utsav Gupta

124

구글 맵 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 %를 사용하십시오.
멍청한 놈

2
허용되는 답변은 때때로 이상한 확대를 유발합니다. 이것은 매력처럼 작동합니다. 이것이 더 나은 대답입니다.
Hüseyin Bülbül

1
이 답변은 수락 된 것보다 잘 작동하며, 수락 된 것은 약간의 위태로운 행동을 유발합니다.
Haytham

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

참고 -이것은 원래 질문에 대한 해결책이 아닙니다. 이것은 위에서 설명한 하위 문제 중 하나에 대한 솔루션입니다 입니다.

솔루션 @andr하는 명확한 설명이 -

바운드에 마커가 하나만있을 때 문제가되고 줌 레벨이 매우 높은 수준 ( 레벨 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도 "기괴한"줌 레벨 문제를 잘 설명하지 못할 것입니다.


좋은 해결책이지만 onMapReady () 안에 "cu"객체를 넣으면이 경우 오작동이 발생합니다. 수신 위치-> 확대 / 축소가 크므로 16-> 사용자가 확대-> 다시 수신 위치 및 카메라가 16 레벨로 되돌립니다 . 레벨 16으로 계속 돌아
Maher Nabil

"Google은
현재이

3

이것은 도움이 될 것입니다 .. 구글 API 데모에서

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

이 같은 일을 완벽하게 수행하는 다른 방법이 있습니다. 화면에 모든 마커를 표시하는 아이디어는 중앙 위도 및 줌 레벨이 필요합니다. 다음은 둘 다를 제공하고 모든 마커의 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.