GoogleMap
には10個のマーカーがあります。できるだけズームインして、すべてのマーカーを表示したままにしたいですか。以前のバージョンではこれはzoomToSpan()
から実現できますが、v2ではそれをどうやって行うのかわかりません。さらに、私は見える必要がある円の半径を知っています。
(おそらく)すべてのプログラムによる地図の移動を行うには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
1つのマーカーのみにこの方法を使用すると、マップのズームが「奇妙な」ズームレベル(特定の場所で使用可能な最大ズームレベルになると考えられます)に設定されることをコメントしています。これは予想されることだと思います。
LatLngBounds bounds
インスタンスは、northeast
と等しいsouthwest
プロパティを持ちます。これは、このbounds
によってカバーされる地球の面積の部分が正確にゼロであることを意味します。 (単一のマーカーには領域がないため、これは論理的です。)bounds
をCameraUpdateFactory.newLatLngBounds
に渡すことによって、bounds
(ゼロ領域を持つ)がマップビュー全体をカバーするようなズームレベルの計算を要求します。Map
オブジェクトはこの値をサポートしていないため、指定された場所で許容されるより合理的な最大レベルに固定されています。別の言い方をすれば、Map
オブジェクトは、単一の場所に対してどのズームレベルを選択すべきかをどのようにして知ることができるのでしょうか。たぶん最適値は20であるべきです(それが特定のアドレスを表すなら)。または11(町を表す場合)または6(国を表す場合) APIはそれほど賢くはないので、決定はあなた次第です。
そのため、markers
が1つの場所しかないかどうかを確認し、そうである場合は、次のいずれかを使用します。
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker.getPosition())
- マーカー位置に移動し、現在のズームレベルをそのままにします。CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker.getPosition(), 12F)
- マーカー位置に行き、ズームレベルを任意に選んだ値に設定します12。次の解決策は、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);
私は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));
}
});
そう
適切なサンプルを入手するには、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
}
});
私のために元気に働いています。
このコードから、地図画面上で特定のズームで複数のマーカーを表示しています。
//宣言された変数
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によってもよく説明されることは決してないでしょう。
これは助けになるだろう..グーグル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)
一般的に私の場合の場所の違いは2つ以下の近隣都市です。
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);
}
中心座標を取得してCameraPositionで使用するには、メソッド "getCenterCoordinate"を使用します。
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で調整できます。