Jetpack 中的地图组成
Posted
技术标签:
【中文标题】Jetpack 中的地图组成【英文标题】:Maps in Jetpack compose 【发布时间】:2021-12-01 00:30:32 【问题描述】:我正在尝试获取一个简单的地图作为我的 mainActivity 来测试使用 compose 的地图是如何工作的。不幸的是,我一开始就失败了一个错误消息,它基本上只说“IllegalStateException”。 我尝试从此处的原始 Google 示例中提取地图代码: https://github.com/android/compose-samples/tree/main/Crane 我尝试重建一个简单的 Composable,在 Google Cloud Platform 上创建了一个 API 密钥并将其添加到我的清单中。
那是MainActivity
:
package com.veloce.mapstesting
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.annotation.FloatRange
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.material.Button
import androidx.compose.material.ButtonDefaults
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import com.google.android.libraries.maps.CameraUpdateFactory
import com.google.android.libraries.maps.GoogleMap
import com.google.android.libraries.maps.MapView
import com.google.android.libraries.maps.model.LatLng
import com.google.maps.android.ktx.addMarker
import com.google.maps.android.ktx.awaitMap
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity()
override fun onCreate(savedInstanceState: Bundle?)
super.onCreate(savedInstanceState)
setContent
val mapView = rememberMapViewWithLifecycle()
MapViewContainer(mapView)
const val InitialZoom = 5f
const val MinZoom = 2f
const val MaxZoom = 20f
@Composable
fun MapViewContainer(map: MapView)
val cameraPosition = remember
LatLng(48.2050491798, 16.3701485194)
LaunchedEffect(map)
val googleMap = map.awaitMap()
googleMap.addMarker position(cameraPosition)
googleMap.moveCamera(CameraUpdateFactory.newLatLng(cameraPosition))
var zoom by rememberSaveable(map) mutableStateOf(InitialZoom)
ZoomControls(zoom)
zoom = it.coerceIn(MinZoom, MaxZoom)
val coroutineScope = rememberCoroutineScope()
AndroidView( map ) mapView ->
val mapZoom = zoom
coroutineScope.launch
val googleMap = mapView.awaitMap()
googleMap.setZoom(mapZoom)
googleMap.moveCamera(CameraUpdateFactory.newLatLng(cameraPosition))
@Composable
private fun ZoomControls(
zoom: Float,
onZoomChanged: (Float) -> Unit
)
Row(Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.Center)
ZoomButton("-", onClick = onZoomChanged(zoom * 0.8f) )
ZoomButton("+", onClick = onZoomChanged(zoom * 1.2f) )
@Composable
fun ZoomButton(text: String, onClick: () -> Unit)
Button(
modifier = Modifier.padding(8.dp),
colors = ButtonDefaults.buttonColors(
backgroundColor = MaterialTheme.colors.onPrimary,
contentColor = MaterialTheme.colors.primary
),
onClick = onClick
)
Text(text = text, style = MaterialTheme.typography.h5)
fun GoogleMap.setZoom(
@FloatRange(from = MinZoom.toDouble(), to = MaxZoom.toDouble()) zoom: Float
)
resetMinMaxZoomPreference()
setMinZoomPreference(zoom)
setMaxZoomPreference(zoom)
这些是MapUtils
:
package com.veloce.mapstesting
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalLifecycleOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import com.google.android.libraries.maps.MapView
import java.lang.IllegalStateException
@Composable
fun rememberMapViewWithLifecycle(): MapView
val context = LocalContext.current
val mapView = remember
MapView(context).apply id = R.id.map
val lifecycleObserver = rememberMapLifecycleObserver(mapView)
val lifecycle = LocalLifecycleOwner.current.lifecycle
DisposableEffect(lifecycle)
lifecycle.addObserver(lifecycleObserver)
onDispose lifecycle.removeObserver(lifecycleObserver)
return mapView
private fun rememberMapLifecycleObserver(mapView: MapView): LifecycleEventObserver =
LifecycleEventObserver _, event ->
when (event)
Lifecycle.Event.ON_CREATE -> mapView.onStart()
Lifecycle.Event.ON_RESUME -> mapView.onResume()
Lifecycle.Event.ON_PAUSE -> mapView.onPause()
Lifecycle.Event.ON_STOP -> mapView.onStop()
Lifecycle.Event.ON_DESTROY -> mapView.onDestroy()
else -> throw IllegalStateException()
我错过了什么吗?
【问题讨论】:
“我刚开始就失败了一个错误消息,它基本上只说“IllegalStateException”“——在你的问题中包含堆栈跟踪仍然是个好主意。虽然详细信息可能无法直接帮助您,但它们可能会帮助那些希望尝试帮助您解决问题的人。 FWIW,piotrprus.medium.com/… 可能会给你一些想法。 考虑为这个错误跟踪器问题添加您的投票,以方便 Google 地图与 Compose 一起使用:issuetracker.google.com/issues/198126189 对您的可组合的 IMPL 很有趣……我以前从未见过具有返回类型的函数实例。我必须自己尝试一下。 【参考方案1】:我不知道你是否正在阅读这篇文章,但你忘记了在生命周期中包含 ON_START 事件,所以你抛出了异常。你也在 ON_CREATE 上调用 onStart。
还可以考虑将生命周期观察者填充到 DisposableEffect 的范围内,并使 DisposableEffect 也知道 mapView(将其作为参数提供)。
【讨论】:
【参考方案2】:Jetpack Compose 的官方谷歌地图库最近发布了,看看吧:
Google Maps Compose
【讨论】:
以上是关于Jetpack 中的地图组成的主要内容,如果未能解决你的问题,请参考以下文章
相对于jetpack中的其他元素创建垂直链组成ConstraintLayout?
JetpackJetpack 简介 ( 官方架构设计标准 | Jetpack 组成套件 | Jetpack架构 | Jetpack 的存在意义 | AndroidX 与 Jetpack 的关系 )
Android Jetpack compose:使用谷歌地图在地图创建时崩溃