如何在Jetpack Compose中实现Google Map全屏切换动画?
实现Google Map全屏切换动画的方案
核心思路
带垂直滚动的Column会限制子元素的高度(滚动容器的子项无法直接占满全屏),因此需要将全屏状态的地图从Column中独立出来,放在根布局的顶层,通过状态控制显示/隐藏,并添加过渡动画。
具体实现步骤
- 用
remember定义全屏状态变量,控制地图的显示模式 - 根布局改用
Box,同时容纳原滚动Column和全屏地图层 - 通过
AnimatedVisibility给全屏地图添加平滑的进入/退出动画 - 让预览态和全屏态的地图共享同一个
cameraPositionState,保持视角一致
修改后的完整代码
@Composable fun YourScreen( innerPadding: PaddingValues, searchVM: SearchViewModel, navController: NavController, buttonList: ButtonList ) { var isFullScreen by remember { mutableStateOf(false) } val cameraPositionState = rememberCameraPositionState { position = CameraPosition.fromLatLngZoom(LatLng(37.7749, -122.4194), 10f) } // 根容器用Box,让全屏地图可覆盖在原内容之上 Box(modifier = Modifier.fillMaxSize()) { // 原可滚动Column内容,全屏时透明隐藏 Column( modifier = Modifier .verticalScroll(rememberScrollState()) .fillMaxSize() .background(Color.Red.copy(alpha = 0.1f)) .padding(innerPadding) .padding(horizontal = 5.dp) .alpha(if (isFullScreen) 0f else 1f) ) { Text( text = "Search", fontWeight = FontWeight.Bold, fontSize = 18.sp, modifier = Modifier.padding(5.dp) ) SearchCard( state = searchVM, onEvent = searchVM, ) Card( modifier = Modifier .padding(horizontal = 30.dp, vertical = 10.dp) .fillMaxWidth() .height(40.dp), elevation = CardDefaults.cardElevation(defaultElevation = 15.dp), colors = CardDefaults.cardColors(containerColor = Color.White) ) { Column( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Search", textAlign = TextAlign.Center) } } Text( text = "Map", fontWeight = FontWeight.Bold, fontSize = 18.sp, modifier = Modifier.padding(start = 5.dp) ) // 预览态地图,全屏时隐藏 AnimatedVisibility(visible = !isFullScreen) { Box( modifier = Modifier .size(400.dp) .padding(10.dp) .clip(shape = RoundedCornerShape(10.dp)) ) { GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) Box( modifier = Modifier .align(Alignment.TopEnd) .padding(10.dp) ) { Icon( imageVector = Icons.Default.Fullscreen, contentDescription = "切换全屏", modifier = Modifier .size(30.dp) .clickable { isFullScreen = true } ) } } } Text( text = "Hello", fontWeight = FontWeight.Bold, fontSize = 18.sp, modifier = Modifier.padding(start = 5.dp) ) buttonList.list.chunked(2).forEach { rowItems -> ListCards( searchVM = searchVM, cardList = rowItems, navController = navController ) } SocialMediaAndAboutUs() } // 全屏态地图,默认隐藏,触发后带动画显示 AnimatedVisibility( visible = isFullScreen, enter = fadeIn() + scaleIn(initialScale = 0.9f), exit = fadeOut() + scaleOut(targetScale = 0.9f) ) { Box(modifier = Modifier.fillMaxSize()) { GoogleMap( modifier = Modifier.fillMaxSize(), cameraPositionState = cameraPositionState ) Box( modifier = Modifier .align(Alignment.TopEnd) .padding(16.dp) ) { Icon( imageVector = Icons.Default.FullscreenExit, contentDescription = "退出全屏", tint = Color.White, modifier = Modifier .size(36.dp) .background(Color.Black.copy(alpha = 0.5f), shape = CircleShape) .padding(4.dp) .clickable { isFullScreen = false } ) } } } } }
关键细节说明
- 根容器用Box:突破
Column的滚动约束,让全屏地图可以覆盖整个界面 - 动画效果:通过
AnimatedVisibility的enter/exit参数实现淡入淡出+缩放的平滑过渡,可根据需求替换为滑动、旋转等其他动画 - 共享地图状态:复用同一个
cameraPositionState,保证预览和全屏模式下地图视角无缝衔接 - 原内容隐藏方式:用
alpha过渡替代直接隐藏,让切换过程更自然
内容的提问来源于stack exchange,提问作者Pawandeep Singh
相关产品推荐
相关产品推荐

