You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 13:54:04