我尝试在地图和我的标记之间放置背景;此图像应始终(!)留在所有标记之后。Android Google Maps - 所有标记背后的自定义背景
我尝试了几种方法,例如, showInfoWindow()
除了背景图像之外的所有标记,但它似乎只会对最后一个有帮助。
然后我尝试了使用GroundOverlay
的解决方案,但我需要我的图像始终保持相同的大小(例如设备大小的一半),而与缩放因子无关。
Android上有这个解决方案吗?
我尝试在地图和我的标记之间放置背景;此图像应始终(!)留在所有标记之后。Android Google Maps - 所有标记背后的自定义背景
我尝试了几种方法,例如, showInfoWindow()
除了背景图像之外的所有标记,但它似乎只会对最后一个有帮助。
然后我尝试了使用GroundOverlay
的解决方案,但我需要我的图像始终保持相同的大小(例如设备大小的一半),而与缩放因子无关。
Android上有这个解决方案吗?
您最好的选择是使用GroundOverlay
来显示背景,在视图更改时添加和删除它,并根据地图的VisibleRegion
计算尺寸,以便它在缩放之间保持正确的大小。
位置
有指定地面叠加层的位置有两种方式:
使用位置:您必须提供的图像地面覆盖层,锚将固定到的LatLng以及覆盖层的宽度(以米为单位)。默认情况下,锚点距图像顶部50%,图像左侧50%。这可以改变。您可以选择提供覆盖层的高度(以米为单位)。如果您未提供叠加层的高度,则会自动计算以保留图像的比例。
使用界限:您必须提供一个包含图像的LatLngBounds。
以下示例使用一OnCameraChangeListener
移除并添加GroundOverlay
,显示在地图上的中心的ic_launcher
绘制,地图的宽度的75%(卸下和在onCameraChange
添加GroundOverlay
事件可确保图像的大小始终与缩放级别无关)。
public class MyMapActivity extends Activity implements OnCameraChangeListener {
GroundOverlay backgroundOverlay = null;
GoogleMap map;
// ...
@Override
public void onCameraChange(final CameraPosition cameraPosition) {
if (backgroundOverlay != null) {
backgroundOverlay.remove();
}
VisibleRegion visibleRegion = map.getProjection()
.getVisibleRegion();
Location nearLeftLocation = new Location("nearLeftLocation");
nearLeftLocation.setLatitude(visibleRegion.nearLeft.latitude);
nearLeftLocation.setLongitude(visibleRegion.nearLeft.longitude);
Location nearRightLocation = new Location("nearRightLocation");
nearRightLocation.setLatitude(visibleRegion.nearRight.latitude);
nearRightLocation.setLongitude(visibleRegion.nearRight.longitude);
float width = nearLeftLocation.distanceTo(nearRightLocation);
GroundOverlayOptions background = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher))
.position(cameraPosition.target, width * 0.75f);
backgroundOverlay = map.addGroundOverlay(background);
}
}
UPDATE:
正如我在对现有GroundOverlay
,而不是添加/在每个摄像头的变化中取出的评论,我们可以和setDimensions
说。
我已经在几个设备上测试过它,它似乎减少了低端设备上的闪烁,但仍然不是完美的解决方案(图像在缩放之间调整大小)。我非常肯定,这是我们可以使用GroundOverlay
的最佳选择。
public class MyMapActivity extends Activity implements OnCameraChangeListener {
GroundOverlay backgroundOverlay = null;
GoogleMap map;
// ...
@Override
public void onCameraChange(final CameraPosition cameraPosition) {
VisibleRegion visibleRegion = map.getProjection().getVisibleRegion();
Location nearLeftLocation = new Location("nearLeftLocation");
nearLeftLocation.setLatitude(visibleRegion.nearLeft.latitude);
nearLeftLocation.setLongitude(visibleRegion.nearLeft.longitude);
Location nearRightLocation = new Location("nearRightLocation");
nearRightLocation.setLatitude(visibleRegion.nearRight.latitude);
nearRightLocation.setLongitude(visibleRegion.nearRight.longitude);
float width = nearLeftLocation.distanceTo(nearRightLocation);
if (backgroundOverlay == null) {
GroundOverlayOptions background = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromResource(R.drawable.ic_launcher))
.position(cameraPosition.target, width * 0.75f);
backgroundOverlay = map.addGroundOverlay(background);
} else {
backgroundOverlay.setPosition(cameraPosition.target);
backgroundOverlay.setDimensions(width * 0.75f);
}
}
}
UPDATE
我已经找到另一种解决方案。如果您的背景是简单的半透明颜色,则可以使用TileOverlay将其设置为低于所有标记。
这个想法是创建一个TileProvider,它总是返回一个非常小(在我的例子中是2×2像素)的图像,将在所有标记下绘制。为确保性能,由TileProvider
返回的Tile
将始终相同。
下面是代码:
public class BackgroundTileProvider implements TileProvider {
private Tile tile;
@Override
public Tile getTile(int x, int y, int zoom) {
if (tile == null) {
// Create a very small (for performance) bitmap with alpha
Bitmap bmp = Bitmap.createBitmap(2, 2, Bitmap.Config.ARGB_8888);
// Draw the desired color to use as background
Canvas canvas = new Canvas(bmp);
canvas.drawColor(Color.argb(150, 255, 0, 0));
// Get the bytes and create the Tile
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bmp.compress(Bitmap.CompressFormat.PNG, 100, stream);
tile = new Tile(2, 2, stream.toByteArray());
}
return tile;
}
}
您需要将TileOverlay添加到您的地图如下:
TileProvider tileProvider = new BackgroundTileProvider();
TileOverlay tileOverlay = map.addTileOverlay(
new TileOverlayOptions().tileProvider(tileProvider));
结果将是这样的:
非常感谢,目前它是最有前途的解决方案,不幸的是图像在缩放变化期间被隐藏;它由于删除/添加而闪烁很多,你能想出一个解决方案如何使这更加顺利吗? – swalkner
您可以尝试在现有的'GroundOverlay'上设置'setPosition'和'setDimensions',而不是在每次更改摄像机时添加/删除它,但是您不会摆脱您陈述的问题。我知道您希望背景能够“跟随”您的相机动作,但考虑到GoogleMaps API(https://developers.google.com/maps/documentation/android-api/events)以及您的要求(你需要把背景放在你的标记下面)这是我能想到的最好的解决方案。也许另一位开发人员可以给出更好的答案... – antonio
可以@downvoter请解释一下吗? – antonio
你可以试试这个,计算dimensi ons根据变焦因子并将这些尺寸应用于GroundOverlay。
float zoomLevel=mMap.getCameraPosition().zoom;
//calculate meters*********************
myBounds = mMap.getProjection().getVisibleRegion().latLngBounds;
myCenter= mMap.getCameraPosition().target;
if (myCenter.latitude==0 || myCenter.longitude==0) {
myCenter=new LatLng(myLocation.getLatitude(),myLocation.getLongitude());
}
LatLng ne = myBounds.northeast;
// r = radius of the earth in statute miles
double r = 3963.0;
// Convert lat or lng from decimal degrees into radians (divide by 57.2958)
double lat1 = myCenter.latitude/57.2958;
double lon1 = myCenter.longitude/57.2958;
final double lat2 = ne.latitude/57.2958;
final double lon2 = ne.longitude/57.2958;
// distance = circle radius from center to Northeast corner of bounds
double dis = r * Math.acos(Math.sin(lat1) * Math.sin(lat2) +
Math.cos(lat1) * Math.cos(lat2) * Math.cos(lon2 - lon1));
//1 Meter = 0.000621371192237334 Miles
double meters_calc=dis/0.000621371192237334;
float factor=1;
if (zoomLevel==15) { // my default zoom level yours can be different
metersoverlay=meters_calc; // global variable metersoverlay set
}
else { // if my zoom level change then I have to calculate dimension scale factor
factor=(float) (meters_calc/metersoverlay);
}
//******************************* now we are ready to set dimension of background overlay
float dimensions=1000*factor;
loadingGroundOverlayBg.setDimensions(dimensions);
哪里你会把这个?在'''onCameraChange-Listener'''?以及如何创建loadingGroundOverlay - 正如@antonio所描述的那样? – swalkner
是的,你可以把它放在'onCameraChanged'上,看看它是否可以工作 和'loadingGroundOverlayBg'是'GroundOverlay'的对象名称。 –
没有必要每次在摄像机上添加/删除覆盖像@antonio所说的那样改变,只需setDimensions即可。 –
这很容易做到。
添加两个标记而不是一个。首先在lat_lng处添加背景作为位图。
事情是这样的:
map.addMarker(new MarkerOptions()
.position(lat_lng)
.anchor(0.5f, 0.5f)
.icon(BitmapDescriptorFactory.fromBitmap(bitmap)));
添加您的标记像平时一样在同一lat_lng。
为每个标记执行上述操作。
我想我不明白它的意思;背景应该总是覆盖整个地图,它不是一个固体图像,但看起来像一个雷达,所以我不能将它添加多次和不同的位置 – swalkner
为什么不简单地为您的标记设置自定义图标?在地图中有大量的标记和GroundOverlays会影响性能,所以我会尽量不设置一个标记和一个GroundOverlay,而应该只有一个标记 – antonio
我的标记有自定义图标,但应该有一个作为背景使用;这是不可能的,因为我不能配置z-index – swalkner
好吧,对不起,我还没有理解你的问题 – antonio