我在谷歌地图上有10个标记。我想要尽可能放大,并保持所有标记都在视野中?在早期版本中,这可以从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
一个评论指出,只对一个标记使用这种方法会导致地图缩放设置为“奇怪的”缩放级别(我认为这是给定位置可用的最大缩放级别)。我认为这是意料之中的,因为:
The LatLngBounds bounds instance will have northeast property equal to southwest, meaning that the portion of area of the earth covered by this bounds is exactly zero. (This is logical since a single marker has no area.) By passing bounds to CameraUpdateFactory.newLatLngBounds you essentially request a calculation of such a zoom level that bounds (having zero area) will cover the whole map view. You can actually perform this calculation on a piece of paper. The theoretical zoom level that is the answer is +∞ (positive infinity). In practice the Map object doesn't support this value so it is clamped to a more reasonable maximum level allowed for given location.
另一种说法是:Map对象如何知道它应该为单个位置选择什么缩放级别?也许最佳值应该是20(如果它代表一个特定的地址)。或者11(如果它代表一个城镇)。或者6个(如果它代表一个国家的话)。API不是那么聪明,决定取决于你。
所以,你应该简单地检查标记是否只有一个位置,如果是这样,使用其中之一:
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker. getposition()) -转到标记位置,保持当前缩放级别不变。 CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker. getposition (), 12F) -进入标记位置,将缩放级别设置为任意选择的值12。
其他回答
我有另一种方法来做同样的事情,效果很好。为了在屏幕上显示所有标记,我们需要一个中长和缩放级别。这里是一个函数,它会给你两个,需要所有标记的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.second));
你可以不用填充来让标记远离屏幕边界,你可以通过-1来调整缩放。
我用一个片段在Kotlin中显示多个标记,解决了同样的问题
首先声明一个标记列表
private lateinit var markers: MutableList<Marker>
在分支的oncreate方法中初始化它
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//initialize markers list
markers = mutableListOf()
return inflater.inflate(R.layout.fragment_driver_map, container, false)
}
在OnMapReadyCallback中将标记添加到标记列表中
private val callback = OnMapReadyCallback { googleMap ->
map = googleMap
markers.add(
map.addMarker(
MarkerOptions().position(riderLatLng)
.title("Driver")
.snippet("Driver")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_RED))))
markers.add(
map.addMarker(
MarkerOptions().position(driverLatLng)
.title("Driver")
.snippet("Driver")
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_GREEN))))
仍然是回调
//create builder
val builder = LatLngBounds.builder()
//loop through the markers list
for (marker in markers) {
builder.include(marker.position)
}
//create a bound
val bounds = builder.build()
//set a 200 pixels padding from the edge of the screen
val cu = CameraUpdateFactory.newLatLngBounds(bounds,200)
//move and animate the camera
map.moveCamera(cu)
//animate camera by providing zoom and duration args, callBack set to null
map.animateCamera(CameraUpdateFactory.zoomTo(10f), 2000, null)
快乐的程序员们
您应该使用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
一个评论指出,只对一个标记使用这种方法会导致地图缩放设置为“奇怪的”缩放级别(我认为这是给定位置可用的最大缩放级别)。我认为这是意料之中的,因为:
The LatLngBounds bounds instance will have northeast property equal to southwest, meaning that the portion of area of the earth covered by this bounds is exactly zero. (This is logical since a single marker has no area.) By passing bounds to CameraUpdateFactory.newLatLngBounds you essentially request a calculation of such a zoom level that bounds (having zero area) will cover the whole map view. You can actually perform this calculation on a piece of paper. The theoretical zoom level that is the answer is +∞ (positive infinity). In practice the Map object doesn't support this value so it is clamped to a more reasonable maximum level allowed for given location.
另一种说法是:Map对象如何知道它应该为单个位置选择什么缩放级别?也许最佳值应该是20(如果它代表一个特定的地址)。或者11(如果它代表一个城镇)。或者6个(如果它代表一个国家的话)。API不是那么聪明,决定取决于你。
所以,你应该简单地检查标记是否只有一个位置,如果是这样,使用其中之一:
CameraUpdate cu = CameraUpdateFactory.newLatLng(marker. getposition()) -转到标记位置,保持当前缩放级别不变。 CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(marker. getposition (), 12F) -进入标记位置,将缩放级别设置为任意选择的值12。
So
我需要使用addOnGlobalLayoutListener来获得适当的示例
例如,你的谷歌地图在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
}
});
用谷歌地图显示所有标记
在这些方法中存储所有标记,并自动缩放显示谷歌地图中的所有标记。
// 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);
}
推荐文章
- 如何在Android中获得一个RadioGroup的选定索引
- 如何分配文本大小在sp值使用java代码
- Manifest合并失败:uses-sdk:minSdkVersion 14
- 为什么Android工作室说“等待调试器”如果我不调试?
- 如何检查我的EditText字段是否为空?
- Android从图库中选择图像
- 后台任务,进度对话框,方向改变-有任何100%工作的解决方案吗?
- Android:垂直对齐多行EditText(文本区域)
- Android无尽列表
- Android room persistent: AppDatabase_Impl不存在
- 错误:执行失败的任务':app:compileDebugKotlin'。>编译错误。详细信息请参见日志
- 在Android中使用URI生成器或使用变量创建URL
- 缩放图像以填充ImageView宽度并保持纵横比
- 列表视图的自定义适配器
- 在Android中设置TextView span的颜色