如何仿Uber实现根据地图左右移动调整上下车点InfoWindow位置?
实现类似Uber的InfoWindow随地图平移调整位置效果
我来帮你搞定这个需求!核心思路是在地图相机停止移动时,计算Marker的屏幕坐标,根据它相对于地图中心的位置动态调整InfoWindow的显示位置,让它始终避开地图边缘,和Uber的逻辑一致。
步骤1:补全并完善你的onCameraIdle逻辑
先把你未完成的代码补全,加上关键的位置判断与锚点调整逻辑:
@Override public void onCameraIdle() { Projection projection = googleMap.getProjection(); // 获取地图容器的中心屏幕坐标 View mapView = ((MapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getView(); if (mapView == null) return; Point mapCenter = new Point(mapView.getWidth() / 2, mapView.getHeight() / 2); // 处理上车点Marker if (Marker != null) { LatLng markerLocation = Marker.getPosition(); Point markerScreenPos = projection.toScreenLocation(markerLocation); // 判断Marker在地图左半区还是右半区 boolean isLeftSide = markerScreenPos.x < mapCenter.x; // 设置InfoWindow锚点:左半区时锚点靠左(InfoWindow显示在Marker右侧),右半区时锚点靠右(InfoWindow显示在Marker左侧) Marker.setInfoWindowAnchor(isLeftSide ? 0.0f : 1.0f, 0.5f); // 刷新InfoWindow位置(如果当前正显示) if (Marker.isInfoWindowShown()) { Marker.hideInfoWindow(); Marker.showInfoWindow(); } } // 处理下车点Marker if (MarkerDrop != null) { LatLng dropMarkerLocation = MarkerDrop.getPosition(); Point dropMarkerScreenPos = projection.toScreenLocation(dropMarkerLocation); boolean isDropLeftSide = dropMarkerScreenPos.x < mapCenter.x; MarkerDrop.setInfoWindowAnchor(isDropLeftSide ? 0.0f : 1.0f, 0.5f); if (MarkerDrop.isInfoWindowShown()) { MarkerDrop.hideInfoWindow(); MarkerDrop.showInfoWindow(); } } }
步骤2:自定义InfoWindow(可选但推荐)
如果你的InfoWindow需要自定义样式,可以实现GoogleMap.InfoWindowAdapter来加载自定义布局,配合锚点调整效果会更精准:
googleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() { @Override public View getInfoWindow(Marker marker) { // 加载自定义布局文件 View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_window, null); // 根据Marker标识设置对应内容 if (marker.equals(Marker)) { ((TextView) infoWindow.findViewById(R.id.info_title)).setText("上车点"); } else if (marker.equals(MarkerDrop)) { ((TextView) infoWindow.findViewById(R.id.info_title)).setText("下车点"); } return infoWindow; } @Override public View getInfoContents(Marker marker) { return null; // 直接使用getInfoWindow返回的完整布局即可 } });
关键逻辑说明
Projection.toScreenLocation:把Marker的地理坐标转换成屏幕像素坐标,以此判断它在地图视图中的相对位置。setInfoWindowAnchor:设置InfoWindow与Marker的对齐锚点,(0.0f, 0.5f)表示InfoWindow左边缘中点和Marker对齐,(1.0f, 0.5f)表示右边缘中点和Marker对齐,完美实现Uber的左右切换效果。- 刷新InfoWindow:调整锚点后需要重新显示InfoWindow,才能让位置更新生效。
额外注意事项
- 确保
Marker和MarkerDrop对象已正确初始化并添加到地图上。 - 如果地图容器尺寸会变化(比如屏幕旋转),无需额外处理,
onCameraIdle会自动触发并重新计算位置。
内容的提问来源于stack exchange,提问作者user9298460
相关产品推荐
相关产品推荐

