У меня есть 10 маркеров в GoogleMap
. Я хочу увеличить как можно больше и держать все маркеры в поле зрения? В более ранней версии это может быть достигнуто с помощью zoomToSpan()
, но в v2 я понятия не имею, как это сделать. Кроме того, я знаю радиус круга, который должен быть видимым.
Android map v2 zoom, чтобы показать все маркеры
Ответ 1
Вы должны использовать класс CameraUpdate
для выполнения (возможно) всех программных движений карты.
Чтобы сделать это, сначала вычислите границы всех маркеров следующим образом:
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (Marker marker : markers) {
builder.include(marker.getPosition());
}
LatLngBounds bounds = builder.build();
Затем получите объект описания движения с помощью factory: 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
В одном примечании отмечается, что использование этого метода только для одного маркера приводит к увеличению масштабирования карты до "причудливого" уровня масштабирования (который, как я полагаю, является максимальным уровнем масштабирования, доступным для данного местоположения). Я думаю, что это ожидается, потому что:
- Экземпляр
LatLngBounds bounds
будет иметь свойствоnortheast
, равноеsouthwest
, что означает, что часть области земли, покрываемая этимbounds
, равна нулю. (Это логично, поскольку у одного маркера нет области.) - Переходя
bounds
вCameraUpdateFactory.newLatLngBounds
, вы по существу запрашиваете расчет такого уровня масштабирования, которыйbounds
(имеющий нулевую область) будет охватывать все виды карты. - Вы можете выполнить этот расчет на листе бумаги. Теоретический уровень масштабирования, который является ответом, равен + & infin; (положительная бесконечность). На практике объект
Map
не поддерживает это значение, поэтому он зажимается до более разумного максимального уровня, разрешенного для данного местоположения.
Другой способ: как может объект Map
узнать, какой уровень масштабирования он должен выбрать для одного места? Возможно, оптимальное значение должно быть 20 (если оно представляет собой конкретный адрес). Или, может быть, 11 (если это город). Или, может быть, 6 (если это страна). API не настолько умный, и решение зависит от вас.
Итак, вы должны просто проверить, имеет ли markers
только одно местоположение, и если да, используйте один из:
-
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition())
- перейдите в положение маркера, оставьте текущий уровень масштабирования неповрежденным. -
CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F)
- перейдите в положение маркера, установите уровень масштабирования на произвольно выбранное значение 12.
Ответ 2
Google Map V2
Следующее решение работает для Android Marshmallow 6 (API 23, API 24, API 25). Это также работает в 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);
Ответ 3
So
Мне нужно было использовать 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
}
});
Ответ 4
Я не мог использовать 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 dimensions."
ошибка:
mMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
@Override
public void onMapLoaded() {
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(builder.build(), 15));
}
});
Ответ 5
Работаю хорошо для меня.
Из этого кода я показываю несколько маркеров с определенным увеличением на экране карты.
//Объявленные переменные
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);
Ответ 6
Примечание. Это не решение исходного вопроса. Это решение одной из обсуждаемых ниже подзадач .
Решение для @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));
Таким образом, у вас никогда не будет проблемы с "причудливым" уровнем масштабирования, который очень хорошо объясняется @andr.
Ответ 7
это поможет.. из google apis demos
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
Ответ 8
У меня была аналогичная проблема, используя следующий код, решив проблему:
CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5)
обычно различия в местоположении в моем случае не более двух соседних городов.
масштабировать, чтобы соответствовать всем маркерам на карте google maps v2
Ответ 9
Используйте метод 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();
}
Ответ 10
У меня есть еще один способ сделать то же самое, что работает отлично. так что идея показать все маркеры на экране, нам нужен центр по длине и уровень масштабирования. вот функция, которая даст вам обоим и потребует в качестве входных данных все объекты-маркеры 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 pair = getCenterWithZoomLevel (l1, l2, l3..); mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(pair.first, pair.second));
Вы можете вместо того, чтобы использовать отступы, чтобы убрать маркеры от границ экрана, вы можете настроить масштабирование на -1.
Ответ 11
Показать все маркеры на карте 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);
}
Ответ 12
//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