You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仿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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:20:36