android高德地图开发如何限制绘制物显示区域

678 阅读4分钟

image.png

需求: 把点亮的城市全部显示 并且显示区域在屏幕的四分之三区域 因为底部有四分之一的区域被遮挡

1.首先我们在点亮 /市级/ 区域时,获取到了市级每个行政区划的边界点,并且还获取到了市级的中心点,我们从中心点开始动手

1.1 我们有一个需要点亮城市的名字集合

private val searchQueue = LinkedList<String>() // 用于存储待搜索的城市列表

1.2 处理城市搜索队列 获取城市的中心点和市级每个行政区划的边界点(具体可以)

// 处理搜索队列
private fun processSearchQueue() {
    if (searchQueue.isNotEmpty()) {
        val city = searchQueue.poll() // 取出队列中的第一个城市
        performSearchForCity(city)
    } else {
        // 如果队列为空,并且已经处理了所有城市,可以执行一些后续操作
        if (processedCities == cityCount) {
            // 所有城市都已处理完毕
            moveMapCenter()
        }
    }
}

1.3 获取到城市的中心点 并且保存到一个集合中

private fun performSearchForCity(city: String) {
    val search = DistrictSearch(context)
    val query = DistrictSearchQuery()
    query.keywords = city // 使用当前遍历到的城市作为关键字
    query.isShowBoundary = true // 是否返回边界值
    query.isShowChild = false
    search.query = query
    // 由于搜索是异步的,我们需要为每个城市设置一个监听器来处理结果
    search.setOnDistrictSearchListener { districtResult ->
        if (districtResult != null && districtResult.aMapException.errorCode == 1000) {
            // 成功获取到行政区划信息
            val districtItems: List<DistrictItem>? = districtResult.district
            val districtItem = districtItems?.firstOrNull()
            val center = districtItem?.center
            center?.let {
                if (center.longitude > 0) {
                    mapLatLngList.add(LatLng(center.latitude, center.longitude))
                }
            }
            processedCities++
            // 记录日志
            YzLog.e("IMineRunFootPrintImpl-》districtItems for $city: ${districtItems.toString()}")
            // 绘制省份和标记
            drawMap(districtItems)
        } else {
            // 处理查询失败的情况
            YzLog.e("IMineRunFootPrintImpl-》DistrictSearch failed for $city: ${districtResult?.aMapException?.errorMessage}")
        }
        // 完成当前搜索后,继续处理队列中的下一个城市
        processSearchQueue()
    }
    // 执行异步搜索
    search.searchDistrictAsyn()
    // 保存当前搜索实例,以便在需要时可以取消或重新配置
    currentSearch = search
}

2 获取到了城市的中心点 并把所有点亮城市区域显示出来

2.1 高德地图 LatLngBounds.Builder().include(latlng) 可以让所有点 都显示在地图区域上 并且获取到边界的四个点

//通过城市中心点集合  计算最小外接矩形
val builder = LatLngBounds.Builder()
for (latlng in points) {
    builder.include(latlng)
}
val originalLatLngBounds = builder.build()
// 2. 获取原始矩形的四个角点
val southwest = originalLatLngBounds.southwest
val northeast = originalLatLngBounds.northeast
val newBounds = LatLngBounds(southwest, northeast)
getCurMap()?.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(newBounds, 0,0,0,paddingBottom))
// 3. 创建多边形对象
val polygonOptions = PolygonOptions()
    .add(southwest)
    .add(northwest)
    .add(northeast)
    .add(southeast)
    .strokeColor(Color.parseColor("#00ff0000")) // 设置边框颜色为暗红色
    .fillColor(Color.argb(128, 139, 0, 0)) // 设置填充颜色为半透明的暗红色
    .strokeWidth(5f) // 设置边框宽度

// 4. 获取地图实例并添加多边形
val aMap = getCurMap() // 假设这是您获取地图实例的方法
aMap?.addPolygon(polygonOptions)

image.png 2.2 因为底部有四分之一的区域遮挡住了 如果底下有地图,就显示不出来 我们先把地图缩小 看看绘制出获取到边界的四个点是否正确

image.png 2.3 因为我们是以中心点来绘制的 所以我城市的其他区域会显示不全 这边的想法是放大地图显示区域的倍数 因为我们知道了地理坐标(经纬度) 可以通过经纬度来实现放大或缩小

// 3. 计算矩形的宽度(纬度差值)和高度(经度差值)
val latDiff = northeast.latitude - southwest.latitude
val lngDiff = northeast.longitude - southwest.longitude

// 4. 根据指定的比例分别放大宽度和高度
val newLatDiff = latDiff * 1.25  // 宽度(纬度差值)放大1.5倍
val newLngDiff = lngDiff * 1.5 // 高度(经度差值)放大1.25倍

// 5. 计算新的西南角点(此角点将作为新矩形的起点)
// 注意:新西南角点的计算需考虑原始矩形中心与新矩形中心的相对位置
val centerLat = southwest.latitude + latDiff / 2
val centerLng = southwest.longitude + lngDiff / 2
// 6. 根据新的西南角点和放大后的宽度、高度,计算其他三个角点
val newSouthwest = LatLng(centerLat - newLatDiff / 2, centerLng - newLngDiff / 2)
val newNorthwest = LatLng(newSouthwest.latitude + newLatDiff, newSouthwest.longitude)
val newNortheast =
    LatLng(newSouthwest.latitude + newLatDiff, newSouthwest.longitude + newLngDiff)
val newSoutheast = LatLng(newSouthwest.latitude, newSouthwest.longitude + newLngDiff)
val newBounds = LatLngBounds(newSouthwest, newNortheast

2.4 这样一来 区域是全屏 但是城市的区域 都显示出来了 但是还是会有遮挡 然后我们通过加padding 来实现显示区域为全屏的四分之三 并且给中心点 绘制标志

val screenHeight =DensityUtils.getScreenHeight(context)
val paddingBottom = screenHeight / 4
getCurMap()?.moveCamera(CameraUpdateFactory.newLatLngBoundsRect(newBounds, 0,0,0,paddingBottom))
// 计算中心点的纬度和经度
val centerLatitude = (newSouthwest.latitude + newNortheast.latitude) / 2.0
val centerLongitude = (newSouthwest.longitude + newNortheast.longitude) / 2.0
curLocation = LatLng(centerLatitude, centerLongitude)

addMarker(centerLatitude, centerLongitude, "中心点")

2.5 最终效果图

image.png