Flutter中CustomInfoWindow无法设置圆角及背景透明问题求助
Flutter中custom_info_window无法设置圆角和透明背景的解决方法
问题描述
在Flutter项目中使用custom_info_window包实现Google Maps标记弹窗时,无法为CustomInfoWindow组件设置borderRadius(圆角)或背景透明样式。已实现承载弹窗内容的ContainerGoogleMaps组件和添加地图标记的MapScreen组件,但无法修改CustomInfoWindow外观,寻求可行方案。
当前弹窗效果:
现有代码
ContainerGoogleMaps组件代码
import 'package:flutter/material.dart'; import 'package:streeti/static/static_colors.dart'; import 'package:streeti/widgets/bold_big_text.dart'; import 'package:streeti/widgets/small_text.dart'; class ContainerGoogleMaps extends StatelessWidget { String title; ContainerGoogleMaps({required this.title, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ Container( width: double.maxFinite, decoration: const BoxDecoration( borderRadius: BorderRadius.only( topLeft: Radius.circular(15), topRight: Radius.circular(15), ), color: Colors.blue, ), child: Text( title, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500), ), ), Container() ], ), ); } }
MapScreen组件代码
import 'package:custom_info_window/custom_info_window.dart'; import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:streeti/pages/plate_withOTP_page.dart'; import 'package:streeti/widgets/bold_big_text.dart'; import 'package:streeti/widgets/bottom_nav.dart'; import 'package:streeti/widgets/container_google_maps_info.dart'; import 'package:streeti/widgets/small_text.dart'; const LatLng consLocation = LatLng(48.355016218833654, 15.813391958051588); const LatLng marker1 = LatLng(48.34161850665899, 15.778319914302879); const LatLng marker2 = LatLng(48.32890042576883, 15.915319080569235); const LatLng marker3 = LatLng(48.286968189915875, 15.841635818003887); const LatLng marker4 = LatLng(48.26770643729367, 15.756396257371149); const LatLng marker5 = LatLng(48.325018246453446, 15.70158482793595); class MapScreen extends StatefulWidget { const MapScreen({super.key}); @override State<MapScreen> createState() => _MapScreenState(); } class _MapScreenState extends State<MapScreen> { late GoogleMapController _mapController; Map<String, Marker> _markers = {}; final _customInfoWindowController = CustomInfoWindowController(); @override Widget build(BuildContext context) { double screenHeight = MediaQuery.of(context).size.height; double redContainerHeight = screenHeight * 0.1; return Scaffold( body: SafeArea( child: Stack( children: [ Column( children: [ Container( padding: EdgeInsets.all(15), height: redContainerHeight, color: Colors.white, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ BoldBigText( text: 'Suchen', fontSize: 18, isBold: true, ), SmallText( text: "Top Betriebe", fontSize: 12, ), ], ), Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ MaterialButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const PlateWIthOTPPage(), ), ); }, shape: CircleBorder(), child: Icon(Icons.search), ), ], ) ], ), ), //! Google maps Expanded( child: ClipRRect( borderRadius: BorderRadius.only( topLeft: Radius.circular(15), topRight: Radius.circular(15), ), child: Container( color: Colors.blue, child: Stack( children: [ GoogleMap( onMapCreated: (controller) { _mapController = controller; _customInfoWindowController.googleMapController = controller; addMarker('test', marker1, 'AAA'); addMarker('test2', marker2, 'VVV'); addMarker('test3', marker3, 'CCCC'); addMarker('test4', marker4, 'AAA'); addMarker('test5', marker5, 'HJHJ'); }, onTap: (location) { _customInfoWindowController.hideInfoWindow!(); }, onCameraMove: (position) { _customInfoWindowController.onCameraMove!(); }, markers: _markers.values.toSet(), initialCameraPosition: CameraPosition(target: consLocation, zoom: 11), ), CustomInfoWindow( controller: _customInfoWindowController, height: 100, width: 250, offset: 50, ) ], ), ), ), ), ], ), //! bottomnav Positioned( bottom: 0, left: 0, right: 0, child: CustomBottomNavigationBar( isNachrichtActive: false, isKarteActive: false, isCommunityActive: false, isProfilActive: false, ), ), ], ), ), ); } //!add markers addMarker(String id, LatLng location, String title) async { var markerIcon = await BitmapDescriptor.fromAssetImage( ImageConfiguration(size: Size(50, 50)), 'lib/assets/images/map_pin3.png'); var marker = Marker( markerId: MarkerId(id), position: location, icon: markerIcon, onTap: () { _customInfoWindowController.addInfoWindow!( ContainerGoogleMaps( title: title, ), location, ); }, ); _markers[id] = marker; setState(() {}); } }
解决方案
问题根源在于两点:一是ContainerGoogleMaps中使用了Scaffold,它自带白色背景会遮挡自定义样式;二是CustomInfoWindow默认有背景色,没有设置透明。按以下步骤修改:
1. 修改ContainerGoogleMaps组件
移除多余的Scaffold和空Container,直接在根Container上设置圆角和透明背景:
import 'package:flutter/material.dart'; // 保留你项目的其他import class ContainerGoogleMaps extends StatelessWidget { final String title; ContainerGoogleMaps({required this.title, Key? key}) : super(key: key); @override Widget build(BuildContext context) { return Container( width: double.maxFinite, padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), // 全圆角 color: Colors.blue.withOpacity(0.9), // 半透明蓝色背景 ), child: Text( title, style: const TextStyle( color: Colors.white, fontSize: 16, fontWeight: FontWeight.w500), textAlign: TextAlign.center, ), ); } }
2. 修改MapScreen中的CustomInfoWindow
给CustomInfoWindow添加backgroundColor: Colors.transparent,让组件背景透明,只显示自定义内容:
CustomInfoWindow( controller: _customInfoWindowController, height: 80, // 调整高度适配修改后的内容 width: 250, offset: 50, backgroundColor: Colors.transparent, // 关键:设置背景透明 )
3. 调整弹窗高度(可选)
根据修改后的ContainerGoogleMaps内容,调整CustomInfoWindow的height参数,避免内容被截断或出现多余空白。
效果说明
修改后,弹窗会显示带圆角的半透明蓝色背景,完全符合自定义样式需求,同时不会被CustomInfoWindow的默认背景干扰。
内容的提问来源于stack exchange,提问作者LukaszAdler
相关产品推荐
相关产品推荐

