に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
コンストラクトを使用して、これが発生するのを待つことができます。詳細は、この回答と残りの回答へのコメントに記載されています。こちらを使用しaddOnGlobalLayoutListener
て、マップ範囲を設定するための完全なコードを見つけることもできます。
明確化2
このメソッドを1つのマーカーのみに使用すると、マップズームが「奇妙な」ズームレベルに設定される(コメントは、特定の場所で使用可能な最大ズームレベルであると私は信じています)と述べています。私はこれが予想されると思います:
LatLngBounds bounds
インスタンスがありますnortheast
と同等の特性をsouthwest
地球の面積の部分はこれでカバーされていることを意味し、bounds
正確にゼロです。(単一のマーカーには領域がないため、これは論理的です。)bounds
にCameraUpdateFactory.newLatLngBounds
あなたは本質的に、このようなAズームレベルの計算要求bounds
(ゼロ面積を有する)全体の地図ビューをカバーします。Map
オブジェクトはこの値をサポートしていないため、指定された場所で許可されるより妥当な最大レベルにクランプされます。別の言い方をすると、Map
オブジェクトは、単一の場所に対してどのズームレベルを選択すればよいかをどのようにして知ることができますか?たぶん、最適な値は20でなければなりません(特定のアドレスを表す場合)。または、おそらく11(それが町を表す場合)。または多分6(それが国を表す場合)。APIはそれほど賢くなく、決定はあなた次第です。
そのmarkers
ため、場所が1つしかないかどうかを確認し、場所がある場合は次のいずれかを使用します。
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition())
-マーカーの位置に移動し、現在のズームレベルをそのままにします。CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F)
-マーカーの位置に移動し、ズームレベルを任意に選択した値12に設定します。addOnGlobalLayoutListener()
、またはpost()
適切でRunnable
。これが、マーカー画面の座標を取得できない理由です-stackoverflow.com/q/14429877/1820695をonCreate
参照してください。ただし、レイアウトが発生する前でも、いくつかのメソッドを使用できます。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);
注 -これは元の質問に対する解決策ではありません。これは、上記のサブ問題の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によって非常に適切に説明される「奇妙な」ズームレベルの問題が発生しなくなります。
これは.. 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
私は同様の問題があり、次のコードを使用して問題を解決しました:
CameraUpdateFactory.newLatLngBounds(bounds, 200, 200, 5)
一般に、私の場合の場所の違いは、2つの近隣都市にすぎません。
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();
}
これと同じことを完璧に行うには、もう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調整できます。
//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