에 10 개의 마커가 있습니다 GoogleMap
. 최대한 확대하고 모든 마커를 계속보고 싶습니다. 이전 버전에서는 이것이 가능 zoomToSpan()
하지만 v2에서는 그렇게하는 방법을 모릅니다. 또한, 볼 필요가있는 원의 반경을 알고 있습니다.
에 10 개의 마커가 있습니다 GoogleMap
. 최대한 확대하고 모든 마커를 계속보고 싶습니다. 이전 버전에서는 이것이 가능 zoomToSpan()
하지만 v2에서는 그렇게하는 방법을 모릅니다. 또한, 볼 필요가있는 원의 반경을 알고 있습니다.
답변:
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
한 의견에서는이 방법을 하나의 마커에만 사용하면지도 확대 / 축소가 "기괴한"확대 / 축소 수준 (주어진 위치에서 사용 가능한 최대 확대 / 축소 수준)으로 설정됩니다. 나는 이것이 다음과 같은 이유로 예상된다고 생각한다.
LatLngBounds bounds
인스턴스 것이다 northeast
동일한 특성 southwest
이 적용 지구의 영역의 부분 즉, bounds
정확히 제로이다. (단일 마커에는 면적이 없으므로 논리적입니다.)bounds
에 CameraUpdateFactory.newLatLngBounds
당신은 본질적으로되도록 줌 레벨의 계산 요청 bounds
(제로 영역을 갖는) 전체지도보기를 다룰 것입니다.Map
객체는이 값을 지원하지 않으므로 주어진 위치에 허용되는보다 합리적인 최대 수준으로 고정됩니다.그것을 넣는 또 다른 방법 : Map
객체가 단일 위치에 대해 어떤 줌 레벨을 선택 해야하는지 알 수 있습니까? 최적의 값은 20이어야합니다 (특정 주소를 나타내는 경우). 아니면 11 일 수도 있습니다 (도시를 나타내는 경우). 또는 6 (국가를 대표하는 경우). API는 현명하지 않으며 결정은 당신에게 달려 있습니다.
따라서 markers
위치가 하나만 있는지 확인 하고 있으면 다음 중 하나를 사용하십시오.
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition())
-마커 위치로 이동하여 현재 확대 / 축소 수준을 그대로 둡니다.CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F)
-마커 위치로 이동하여 줌 레벨을 임의로 선택된 값 12로 설정하십시오.addOnGlobalLayoutListener()
또는 post()
적절한 것을 사용 하는 것 Runnable
입니다. 이것이 바로 마커 화면 좌표를 얻을 수없는 이유입니다 ( stackoverflow.com/q/14429877/1820695onCreate
참조). 그러나 레이아웃이 발생하기 전에 몇 가지 방법을 사용할 수 있습니다. 와 4 PARAMS . CameraUpdateFactory.newLatLngBounds()
다음 솔루션은 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);
그래서
적절한 샘플을 얻으려면 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
}
});
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));
}
});
나를 위해 잘 작동합니다.
이 코드에서지도 화면에 특정 확대 / 축소로 여러 개의 마커를 표시하고 있습니다.
// 선언 된 변수
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);
참고 -이것은 원래 질문에 대한 해결책이 아닙니다. 이것은 위에서 설명한 하위 문제 중 하나에 대한 솔루션입니다 입니다.
솔루션 @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도 "기괴한"줌 레벨 문제를 잘 설명하지 못할 것입니다.
이것은 도움이 될 것입니다 .. 구글 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
비슷한 코드를 사용하여 다음 코드를 사용하여 문제를 해결했습니다.
CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5)
일반적으로 제 경우의 위치 차이는 이웃 도시 두 개를 넘지 않습니다.
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);
}
"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();
}
이 같은 일을 완벽하게 수행하는 다른 방법이 있습니다. 화면에 모든 마커를 표시하는 아이디어는 중앙 위도 및 줌 레벨이 필요합니다. 다음은 둘 다를 제공하고 모든 마커의 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 씩 확대 / 축소를 조정할 수 있습니다.
//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