ฉันมี 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
หนึ่งความคิดเห็นตั้งข้อสังเกตว่าการใช้วิธีนี้สำหรับตัวทำเครื่องหมายเพียงหนึ่งผลในการซูมแผนที่ตั้งค่าระดับการซูม "แปลกประหลาด" (ซึ่งฉันเชื่อว่าเป็นระดับการซูมสูงสุดพร้อมใช้งานสำหรับตำแหน่งที่กำหนด) ฉันคิดว่านี่เป็นสิ่งที่คาดหวังเพราะ:
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)
- ไปที่ตำแหน่งเครื่องหมายกำหนดระดับการซูมเป็นค่าที่เลือกโดยพลการ 12addOnGlobalLayoutListener()
หรือที่มีความเหมาะสมpost()
Runnable
นี่คือเหตุผลที่ไม่สามารถทำพิกัดหน้าจอของตัวทำเครื่องหมายได้onCreate
- ดูstackoverflow.com/q/14429877/1820695อย่างไรก็ตามคุณสามารถใช้วิธีการบางอย่างก่อนที่จะเกิดเค้าโครง - เช่น CameraUpdateFactory.newLatLngBounds()
กับ4 params
โซลูชันต่อไปนี้ใช้ได้กับ 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 Map ของคุณอยู่ใน 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 2 -
มันเป็นปัญหาจริงๆเมื่อมีเครื่องหมายเพียงอันเดียวในขอบเขตและเนื่องจากระดับการซูมถูกตั้งไว้ที่ระดับสูงมาก ( ระดับ 21 ) และ Google ไม่มีวิธีการตั้งค่าระดับการซูมสูงสุด ณ จุดนี้ สิ่งนี้สามารถเกิดขึ้นได้เมื่อมีเครื่องหมายมากกว่า 1 ตัว แต่สิ่งเหล่านี้อยู่ใกล้กัน จากนั้นปัญหาเดียวกันก็จะเกิดขึ้นเช่นกัน
การแก้ปัญหา - สมมติว่าคุณต้องการให้แผนที่ของคุณไม่เกินกว่าระดับการซูม 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)
โดยทั่วไปแล้วความแตกต่างของสถานที่ตั้งในกรณีของฉันคือไม่เกินสองเมืองเพื่อนบ้าน
แสดงเครื่องหมายทั้งหมดด้วยแผนที่ 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);
}
ฟังก์ชั่นนี้คืนค่าวัตถุคู่ที่คุณสามารถใช้เช่น
คู่คู่ = 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