android - Jetpack 中的地图组成
问题描述
我正在尝试获取一个简单的地图作为我的 mainActivity 来测试使用 compose 的地图是如何工作的。不幸的是,我一开始就失败了一个错误消息,它基本上只说“IllegalStateException”。我尝试从此处的原始 Google 示例中提取地图代码: https ://github.com/android/compose-samples/tree/main/Crane 我尝试重建一个简单的 Composable,并在Google Cloud Platform 并将其添加到我的清单中。
那就是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()
}
}
我错过了什么?
解决方案
我不知道您是否正在阅读此内容,但您忘记在生命周期中包含 ON_START 事件,因此您正在抛出异常。您也在 ON_CREATE 上调用 onStart。
还要考虑将生命周期观察者填充到 DisposableEffect 的范围内,并使 DisposableEffect 也知道 mapView(将其作为参数提供)。
推荐阅读
- typescript - 使用 Typescript 和 React 三纤维的着色器
- angular - 使用 Angular 和 bootstrap 5 beta 找不到 VS 代码 CSS 类选择器
- eslint - 配置 Rider 以在解决方案工具窗口中的错误中显示 ESLint 错误/警告
- python - 有没有办法在熊猫中进行滚动排名?
- javascript - 如何从 require.context 获取完整路径?
- python - 在同一个 shell 中运行 python 文件
- angular - 无法使用打字稿在可观察的对象列表中使用过滤器
- apache-spark - 错误:运行 spark-submit 时缺少应用程序资源
- ruby-on-rails - 迁移到 Rails 6.1 后,使用 RSpec 不推荐使用 connection_config 警告
- python - python中简单RGB动画的问题