我有一个LatLng点列表,我想在GoogleMap上显示为标记。 我目前正在计算一个适合我所有观点的摄像机视图:
首先,我用我的所有点计算LatLngBounds。
Iterator<LatLng> i = items.iterator();
LatLngBounds.Builder builder = LatLngBounds.builder();
while (i.hasNext()) {
builder.include(i.next());
}
LatLngBounds bounds = builder.build();
然后我使用适当的方法:
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds, padding);
这个更新提供了一个很好的视图,我的所有点,一些不错的填充。
问题
我想为paddingTop,paddingBottom,paddingLeft和paddingRight应用不同的值。也就是说,我两边都没有任何东西,然后我在顶部有一个浮动工具栏(约50dp
),底部有一张浮动卡片(约200dp
)。
如果我没有添加填充,顶部工具栏或底部卡片将覆盖一些点。
如果我添加最大填充(200dp
),那么顶部,左侧和右侧都会有巨大的间隙。有什么想法吗?
__________________________
| ___________o__________ |
| | | |
| |____________________|o|
| o |
| o |
| o |
| MAP |
| o |
| o |
| ______________________ |
| | | |
|o| | |
| | |o|
| |____________________| |
|____________________o___|
我现在唯一的想法是,获取地图宽度(以像素为单位),获取Lng中的地图宽度(未明确定义),找到像素/ lng比率,将所需的填充从像素转换为lng,然后重新计算LatLngBounds添加假远离我原始界限的点(每边一个)。
答案 0 :(得分:1)
这似乎有效,但我会等待更好的解决方案。
您需要传递包含地图的视图的宽度和高度(以像素为单位),以便我们可以计算像素到投影坐标系数。
然后在Rect
对象中传递所需的填充。
如果你有很多分数,这可能最适合在后台任务中运行。
public static CameraUpdate computeCameraView(final List<LatLng> items,
final GoogleMap map, final Rect padding,
final int viewWidth, final int viewHeight) {
// Compute bounds without padding
Iterator<LatLng> i = items.iterator();
LatLngBounds.Builder builder = LatLngBounds.builder();
while (i.hasNext()) {
builder.include(i.next());
}
LatLngBounds bounds = builder.build();
// Create a first CameraUpdate and apply
CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(bounds, 0);
map.moveCamera(cameraUpdate);
// Convert padding to lat/lng based on current projection
bounds = map.getProjection().getVisibleRegion().latLngBounds;
double mapWidth = bounds.northeast.longitude - bounds.southwest.longitude;
double mapHeight = bounds.northeast.latitude - bounds.southwest.latitude;
double pixelToLng = mapWidth / viewWidth;
double pixelToLat = mapHeight / viewHeight;
padding.top = (int) (padding.top * pixelToLat);
padding.bottom = (int) (padding.bottom * pixelToLat);
padding.left = (int) (padding.left * pixelToLng);
padding.right = (int) (padding.right * pixelToLng);
// Now padding holds insets in lat/lng values.
// Let's create two fake points and bound
LatLng northEast = new LatLng(bounds.northeast.latitude + padding.top,
bounds.northeast.longitude + padding.right);
LatLng southWest = new LatLng(bounds.southwest.latitude - padding.bottom,
bounds.southwest.longitude - padding.left);
LatLngBounds newBounds = new LatLngBounds.Builder()
.include(northEast).include(southWest).build();
return CameraUpdateFactory.newLatLngBounds(newBounds, 0);
}
这里的弱点是double mapWidth = bounds.northeast.longitude - bounds.southwest.longitude
。你不能像那样计算经度,因为它是一个循环变量(即如果可见区域穿过180子午线就会出现问题)。 我会调查一下。
这应该足够了:
public static double computeLngDistance(LatLng east, LatLng west) {
if (east.longitude <= 0 && west.longitude >= 0) {
// We are crossing the 180 line.
return (east.longitude + 180d) + (180d - west.longitude);
} else {
return east.longitude - west.longitude;
}
}
答案 1 :(得分:0)
实际上有一个更简单,更短的解决方案,只需要三行代码。 感谢https://stackoverflow.com/a/27937256/10035225提供解决方案。
首先,将工具栏和底部卡片的大小转换为像素。
然后,添加以下三行代码:
map.setPadding(left, top, right, bottom); map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 0)); map.setPadding(0,0,0,0);
第一行:顶部和底部填充是您的toolbar and bottom card size plus some extra
,左侧和右侧可以是任何填充,只要看起来不错即可。
第二行:将相机移动/设置动画到remember to set the padding to 0
的边界,因为您不需要任何额外的填充,因为您已经在第一行进行了设置。
第三行:设置地图填充back to original padding
(在我的情况下为0),因为第一行中设置的地图填充是永久的。
就是这样,然后您就可以了!希望对您有帮助!
答案 2 :(得分:0)
您可以使用
public static CameraUpdate newLatLngBounds (LatLngBounds bounds, int width, int height, int padding)
返回一个 CameraUpdate 来转换相机,使得 指定的纬度/经度边界以屏幕为中心 以最大可能缩放指定尺寸的边界框 等级。您可以指定额外的填充,以进一步限制 边界框的大小。
您将定义一个宽度和高度以地图可用区域为中心的框。然后边界将在该框内尽可能地居中和缩放。
您可以通过该框“模拟”填充,而无需对地图应用填充(然后无需移动地图叠加层,例如水印等)。
如果您想要 16dp 的水平填充,您将框的宽度设置为:mapWidth - dpToPx(2 * 16)
该方法的局限性在于,由于框居中,因此左右填充必须相同。 (顶部和底部相同)。
最后的想法:
当地图有填充时,会发生一些奇怪的事情。要么将地图的填充应用于您定义的框,要么发生其他事情。
当我将框的高度定义为 mapHeight - verticalPaddingOfTheMap
时,结果并不如预期。我终于放了 mapHeight
,一切都很好。
如果您操作具有填充的地图,请记住这一点