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

地图投影在非18F缩放级别异常,求无需重复移相机的解决方案

解决方案

问题根源

  1. 地图未完全初始化时调用投影API:首次调用centerMap时,Google Maps的Projection对象尚未就绪,导致toScreenLocation返回异常坐标(如日志中的负数值),进而计算出错误的目标经纬度。
  2. 强制固定缩放级别:每次调用moveCamera都硬编码缩放级别为18F,不仅破坏原有缩放体验,还会导致投影计算在缩放变化过程中不稳定。
  3. 偏移计算逻辑错误:原代码中的length计算逻辑复杂且结果不准确,无法正确将用户位置偏移到抽屉上方的目标区域。

修复步骤

1. 等待地图完全加载后执行首次调整

Google Maps的Projection只有在地图渲染完成后才能正常工作,因此需要监听OnMapLoadedCallback,在地图就绪后再执行首次位置调整:

// 初始化GoogleMap时添加监听
googleMap.setOnMapLoadedCallback {
    // 传入实际的屏幕高度和抽屉高度
    centerMap(screenHeight, drawerHeight)
}

2. 优化偏移计算逻辑

重新推导偏移量:我们需要让用户位置的屏幕Y坐标落在抽屉顶部区域的中心,即屏幕总高度减去抽屉高度后的一半。偏移量为目标Y坐标与原中心Y坐标的差值:

fun centerMap(height: Int, drawerHeight: Int) {
    LocationDataProvider.location?.let { userLocation ->
        val userLatLng = LatLng(userLocation.lat, userLocation.lng)
        // 获取用户位置当前的屏幕坐标
        val screenPoint = googleMap.projection.toScreenLocation(userLatLng)
        
        // 计算目标屏幕Y坐标:抽屉上方区域的垂直中心
        val targetScreenY = (height - drawerHeight) / 2
        // 计算需要偏移的Y值
        val offsetY = targetScreenY - screenPoint.y
        
        // 计算调整后的屏幕坐标
        val adjustedScreenPoint = Point(screenPoint.x, screenPoint.y + offsetY)
        // 转换回经纬度
        val targetCameraLatLng = googleMap.projection.fromScreenLocation(adjustedScreenPoint)
        
        moveCamera(targetCameraLatLng)
    }
}

3. 保留当前缩放级别,避免强制固定

修改moveCamera方法,使用地图当前的缩放级别,而非硬编码的18F,确保投影计算稳定:

fun moveCamera(location: LatLng) {
    val currentZoom = googleMap.cameraPosition.zoom
    val cameraUpdate = CameraUpdateFactory.newLatLngZoom(location, currentZoom)
    googleMap.animateCamera(cameraUpdate)
}

4. 避免在相机移动过程中执行投影计算

添加OnCameraIdleListener,确保仅在相机稳定后执行位置调整,防止异步动画导致的投影异常:

private var needAdjustPosition = false

// 初始化时设置监听
googleMap.setOnCameraIdleListener {
    if (needAdjustPosition) {
        centerMap(screenHeight, drawerHeight)
        needAdjustPosition = false
    }
}

// 需要调整位置时,设置标志位而非直接调用
fun triggerPositionAdjust() {
    needAdjustPosition = true
}

额外注意事项

  • 确保screenHeight是地图容器的实际高度,而非整个屏幕高度(如果地图不是全屏的话)。
  • 若需要周期性调整位置(如每5秒),需先检查相机是否处于稳定状态(通过googleMap.isCameraMoving判断),避免在动画过程中调用投影API。

内容的提问来源于stack exchange,提问作者Ali

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 04:50:23