Flutter Google Map自定义图片标记与SpinKit无法居中显示在地图上
问题解决方法
根因分析
你当前的布局结构存在错误:Stack 下只有一个 Column 子组件,自定义标记、SpinKit加载动画被放在了 Column 内部,和地图、底部白色容器是垂直排列的同级组件,自然会显示在地图下方的底部容器区域,无法叠加在地图图层上。Stack 的层叠效果仅对直接放在其 children 数组内的平级组件生效。
修复步骤
- 将自定义标记、SpinKit组件从
Column内部移出,放到Stack的children列表中,排在Column的后方(后方的组件层级更高,会覆盖在前方组件上层) - 给标记组件添加向下的偏移量,让标记底部的尖端刚好对准地图中心(标记图片的默认中心点会和屏幕中心对齐,可根据你的图片尺寸调整偏移数值)
- 可根据
_locating状态控制SpinKit的显隐,避免加载完成后还占用显示层级
修改后的核心代码
setState((){ currentLocation = LatLng(locationData.latitude, locationData.longitude); }); void onCreated(GoogleMapController controller){ _mapController = controller; } return Scaffold( body: SafeArea( child:Stack( children:[ // 底层布局:地图+底部信息容器 Column( children:[ Expanded( child: GoogleMap( initialCameraPosition: CameraPosition( target: currentLocation, zoom:14.4746, ), zoomControlsEnabled: false, minMaxZoomPreference: MinMaxZoomPreference(1.5,20.8), myLocationEnabled: true, myLocationButtonEnabled: true, mapType: MapType.normal, mapToolbarEnabled: true, onCameraMove: (CameraPosition position) { setState((){ _locating=true; }); locationData.onCameraMove(position); }, onMapCreated: onCreated, onCameraIdle: (){ setState((){ _locating=false; }); locationData.getMoveCamera(); }, ), ), // 底部白色信息容器 Container( height:230, width:MediaQuery.of(context).size.width, color: Colors.white, child:Column( crossAxisAlignment: CrossAxisAlignment.start, children:[ _locating ? LinearProgressIndicator( backgroundColor: Colors.transparent, valueColor: AlwaysStoppedAnimation<Color>(Theme.of(context).primaryColor), ) : Container(), Padding( padding: const EdgeInsets.only(left: 10, right: 20), child: TextButton.icon( onPressed:(){}, icon: Icon( Icons.location_searching, color: Theme.of(context).primaryColor, ), label: Flexible( child: Text( _locating ? 'Locating' : locationData.selectedAddress.featureName, overflow:TextOverflow.ellipsis, style: TextStyle( fontWeight:FontWeight.bold, fontSize: 20, color: Colors.black, ), ), ), ), ), Padding( padding: const EdgeInsets.only(left: 20, right: 20), child: Text( _locating ? '': locationData.selectedAddress.addressLine, style: TextStyle(color:Colors.black54), ), ), SizedBox(height:30,), Padding( padding: const EdgeInsets.all(15.0), child: SizedBox( width: MediaQuery.of(context).size.width-40, child: AbsorbPointer( absorbing: _locating ? true : false, child: TextButton( style:TextButton.styleFrom( backgroundColor:_locating ? Colors.grey: Theme.of(context).primaryColor, ), onPressed:(){ if(_loggedIn==false){ Navigator.pushNamed(context, LoginScreen.id); } else{ _auth.updateUser( id: user.uid, number: user.phoneNumber, latitude:locationData.latitude, longitude:locationData.longitude, address: locationData.selectedAddress.addressline, ); Navigator.pushNamed(context, HomeScreen.id); } }, child: Text( 'CONFIRM LOCATION', style: TextStyle( color: Colors.white, ), ), ), ), ), ), ], ), ), ], ), // 叠加层1:固定在中心的自定义标记 Center( child: Container( height:50, // 可根据标记图片尺寸调整偏移量,让尖端对准地图中心 margin:EdgeInsets.only(bottom:40), child: Image.asset('images/marker.png'), ), ), // 叠加层2:加载动画,仅定位过程中显示 if (_locating) Center( child: SpinKitPulse( color:Colors.black54, size:100.0, ) , ), ], ), ), );
内容的提问来源于stack exchange,提问作者vansika
相关产品推荐
相关产品推荐

