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

求基于Kotlin与Jetpack Compose的Android端OpenStreetMap地图可组合函数

在Jetpack Compose中集成OpenStreetMap(基于osmdroid)

1. 配置依赖与权限

首先引入最新版osmdroid依赖(规避老旧版本兼容问题),在app/build.gradle.kts(或build.gradle)中添加:

dependencies {
    implementation("org.osmdroid:osmdroid-android:6.1.18")
    implementation("org.osmdroid:osmdroid-mapsforge:6.1.18") // 可选,用于MapsForge瓦片源
}

在AndroidManifest.xml中添加必要权限:

<!-- 加载地图瓦片所需网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 瓦片缓存所需存储权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
<!-- 可选:显示当前位置所需定位权限 -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

2. 封装地图展示的Composable函数

利用Compose的AndroidView组件封装osmdroid的MapView,同时处理好View生命周期:

import android.content.Context
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.viewinterop.AndroidView
import org.osmdroid.config.Configuration
import org.osmdroid.tileprovider.tilesource.TileSourceFactory
import org.osmdroid.util.GeoPoint
import org.osmdroid.views.MapView
import org.osmdroid.views.overlay.Marker

@Composable
fun OSMMap(
    modifier: Modifier = Modifier,
    initialLat: Double = 39.9042,
    initialLon: Double = 116.4074,
    initialZoom: Double = 10.0
) {
    val context = LocalContext.current
    // 初始化osmdroid全局配置
    remember {
        Configuration.getInstance().load(
            context,
            context.getSharedPreferences("osmdroid", Context.MODE_PRIVATE)
        )
    }

    // 创建并缓存MapView实例
    val mapView = remember {
        MapView(context).apply {
            setTileSource(TileSourceFactory.MAPNIK) // 设置OpenStreetMap官方瓦片源
            setMultiTouchControls(true) // 启用多点触控缩放、拖拽
            controller.setZoom(initialZoom)
            controller.setCenter(GeoPoint(initialLat, initialLon))
        }
    }

    // 处理MapView销毁逻辑
    DisposableEffect(Unit) {
        onDispose {
            mapView.onDetach()
            mapView.destroyDrawingCache()
        }
    }

    // 将MapView嵌入Compose布局
    AndroidView(
        factory = { mapView },
        modifier = modifier.fillMaxSize()
    ) { view ->
        // 示例:添加初始位置标记
        val marker = Marker(view).apply {
            position = GeoPoint(initialLat, initialLon)
            setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
            title = "初始位置"
        }
        view.overlays.add(marker)
        view.invalidate()
    }
}

3. 在页面中调用Composable

直接在你的Compose页面中使用:

@Composable
fun MapScreen() {
    // 若需定位功能,可在此添加动态权限请求逻辑
    OSMMap(modifier = Modifier.fillMaxSize())
}

常见问题排查

  • 地图加载失败:检查网络权限是否授予、设备网络状态,或更换瓦片源(如TileSourceFactory.OPENSTREETMAP)
  • 崩溃问题:确保osmdroid版本与项目SDK版本兼容,避免使用过时依赖
  • 权限异常:Android 6.0+需动态申请ACCESS_FINE_LOCATION和WRITE_EXTERNAL_STORAGE权限

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 08:40:12