如何在Jetpack Compose中使用自定义Composable作为地图标记图标
在Jetpack Compose的Google Map中使用自定义Composable作为标记图标
要将自定义Composable转换为Google Map Marker所需的BitmapDescriptor,可以通过将Composable渲染到ComposeView并转换为Bitmap来实现,具体步骤如下:
1. 实现Composable转BitmapDescriptor的工具函数
创建工具函数负责将传入的Composable渲染为BitmapDescriptor:
import android.content.Context import android.view.View import android.view.View.MeasureSpec import androidx.compose.runtime.Composable import androidx.compose.ui.node.LayoutNode import androidx.compose.ui.platform.ComposeView import com.google.android.gms.maps.model.BitmapDescriptor import com.google.android.gms.maps.model.BitmapDescriptorFactory @Composable fun composableToBitmapDescriptor( context: Context, content: @Composable () -> Unit ): BitmapDescriptor { val composeView = ComposeView(context).apply { setContent { content() } // 测量并布局ComposeView,确保Composable正确绘制 val widthSpec = MeasureSpec.makeMeasureSpec( LayoutNode.DefaultWidth, MeasureSpec.UNSPECIFIED ) val heightSpec = MeasureSpec.makeMeasureSpec( LayoutNode.DefaultHeight, MeasureSpec.UNSPECIFIED ) measure(widthSpec, heightSpec) layout(0, 0, measuredWidth, measuredHeight) } val bitmap = composeView.drawToBitmap() return BitmapDescriptorFactory.fromBitmap(bitmap) }
2. 在Google Map中使用自定义Marker
自定义Marker Composable(你的原有代码)
import androidx.compose.foundation.background import androidx.compose.foundation.border import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.rotate import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp @Composable fun CustomMarker() { Box( modifier = Modifier .size(width = 85.dp, height = 40.dp) ) { Box( modifier = Modifier .size(40.dp) .rotate(45f) .clip(RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp, bottomStart = 20.dp)) .border( 2.dp, color = Color.White, shape = RoundedCornerShape(topStart = 20.dp, topEnd = 20.dp, bottomStart = 20.dp) ) .background( brush = Brush.verticalGradient( listOf( Color(0xff11A5CF), Color(0xff04CFBB) ) ) ), contentAlignment = Alignment.Center ) } }
修改后的Google Map代码
import android.util.Log import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.runtime.Composable import androidx.compose.runtime.derivedStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.mutableIntStateOf import androidx.compose.ui.platform.LocalContext import com.google.android.gms.maps.model.CameraPosition import com.google.android.gms.maps.model.LatLng import com.google.maps.android.compose.GoogleMap import com.google.maps.android.compose.Marker import com.google.maps.android.compose.MarkerState import com.google.maps.android.compose.rememberCameraPositionState @Composable fun MapScreen() { val latLongList by remember { mutableStateOf( listOf( LatLng(23.091579064649835,72.53389410674572), LatLng(22.32911404585704, 70.79109091311693), LatLng(24.5791114644088, 72.69674610346556), LatLng(22.356990318569245, 73.18480521440506), LatLng(21.155952265072994, 72.84413181245327) ) ) } var index by remember { mutableIntStateOf(0) } val cameraState = rememberCameraPositionState { position = CameraPosition(latLongList[index], 15f, 0f, 0f) } val context = LocalContext.current GoogleMap( modifier = Modifier.fillMaxSize(), onMapClick = { latLng -> Log.d("location", "${latLng.latitude} and ${latLng.longitude}") }, cameraPositionState = cameraState ) { latLongList.forEachIndexed { _, latLng -> val markerState = rememberMarkerState(position = latLng) // 缓存图标,避免重复生成提升性能 val markerIcon by remember { derivedStateOf { composableToBitmapDescriptor(context) { CustomMarker() } } } Marker( state = markerState, icon = markerIcon ) } } }
注意事项
- 使用
remember和derivedStateOf缓存生成的BitmapDescriptor,避免每次重组重新渲染Composable - 确保自定义Marker的尺寸固定,避免测量异常
- 若项目未包含相关依赖,需确保添加
androidx.compose.ui:ui-viewbinding(通常已包含在Compose核心依赖中)
内容的提问来源于stack exchange,提问作者A3_132_ kaushal_satani
相关产品推荐
相关产品推荐

