【发布时间】:2022-01-08 10:21:29
【问题描述】:
我正在尝试构建一个可以导航到多个不同屏幕的应用程序(使用底部导航)。
其中一个屏幕,startDestination,是一个谷歌地图视图,查看Official compose example: Crane 以使其工作,它确实如此。
但是,当导航到另一个屏幕并返回时,MapView 会重新组合并缓慢重新加载。我们从初始相机位置、缩放级别等开始返回。可能有一种方法可以remember 并重新应用这些属性,但我更感兴趣的是保持 Google 地图视图的完整状态不变。 (查看当前适用于 Android 的 Google Maps 应用程序,它完全符合我的要求,尽管他们没有使用 Jetpack Compose)
有没有办法做到这一点?
我已经rememberMapView
@Composable
fun rememberMapViewWithLifecycle(): MapView {
val context = LocalContext.current
val mapView = remember {
MapView(context).apply {
id = R.id.map
}
}
val lifecycle = LocalLifecycleOwner.current.lifecycle
DisposableEffect(lifecycle, mapView) {
// Make MapView follow the current lifecycle
val lifecycleObserver = getMapLifecycleObserver(mapView)
lifecycle.addObserver(lifecycleObserver)
onDispose {
lifecycle.removeObserver(lifecycleObserver)
}
}
return mapView
}
private fun getMapLifecycleObserver(mapView: MapView): LifecycleEventObserver =
LifecycleEventObserver { _, event ->
when (event) {
Lifecycle.Event.ON_CREATE -> mapView.onCreate(Bundle())
Lifecycle.Event.ON_START -> 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()
}
}
为了提供更多上下文,MapView 位于此屏幕的顶部
@ExperimentalMaterialApi
@Composable
fun MapsScreen(
modifier: Modifier = Modifier,
viewModel: EventViewModel = viewModel()
) {
...
val mapView = rememberMapViewWithLifecycle()
MapsScreenView(modifier, uiState, mapView)
}
我尝试过的完全不同的方法是通过BackdropScaffold(inScaffold,因为我想要BottomBar..),其中backLayerContent 是MapsScreen() 和frontLayerContent 是其他屏幕,“正面”已配置为在活动时覆盖整个屏幕。这感觉真的很丑陋和可怕,但它有点工作..
Scaffold(
topBar = {
SmallTopAppBar(
title = { Text(text = "Test") },
)
},
bottomBar = {
BottomBar(navController) { screen ->
showMaps = screen == Screen.MainMaps
coroutineScope.launch {
if (showMaps) scaffoldState.reveal() else scaffoldState.conceal()
}
}
},
content = { innerPadding ->
Box(modifier = Modifier.padding(innerPadding)) {
BackdropScaffold(
scaffoldState = scaffoldState,
appBar = { },
frontLayerContent = {
EventsScreen()
},
backLayerContent = {
MapsScreen()
},
peekHeight = if (showMaps) 300.dp else 0.dp,
headerHeight = if (showMaps) BackdropScaffoldDefaults.HeaderHeight else 0.dp,
gesturesEnabled = showMaps
)
}
}
)
有没有人遇到同样的问题并找到了实际的解决方案? (我猜我们真的需要 Jetpack Compose 支持,而不是 AndroidView 方法)
【问题讨论】:
-
也许使用 rememberSaveable (developer.android.com/jetpack/compose/state#restore-ui-state) 可以解决问题?
-
感谢您的建议!我认为这适用于可以打包或可以使用 Saver 保存的类,我不确定如何将其应用于
MapView
标签: android google-maps android-jetpack-compose android-jetpack