【问题标题】:Fix google map marker in center修复中心的谷歌地图标记
【发布时间】:2019-05-08 05:15:30
【问题描述】:

在我的颤振应用中。我正在使用 google_maps_plugin 。链接是https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter。 我想在拖动地图后将标记固定在地图中心而不移动。 我想要它喜欢http://jsfiddle.net/UuDA6/ 在我的代码中,我使用MarkerOption 来放置标记。

    MarkerOptions options = new MarkerOptions(   
        alpha: 1.0,
        anchor: Offset(0.5, 1.0),
        consumeTapEvents: false,
        draggable: false,
        flat: false,
        icon: BitmapDescriptor.defaultMarker,
        infoWindowAnchor: Offset(0.5, 0.0),
        infoWindowText: InfoWindowText.noText,
        position: LatLng(17.411439, 78.5486697),
        rotation: 0.0,
        visible: true,
        zIndex: 0.0,
    );

但是在position我想知道如何给出地图的中心。

如果有人对此有任何想法,请分享。

【问题讨论】:

    标签: google-maps dart flutter


    【解决方案1】:

    实际上,通过google_maps_flutter: ^0.4.0 的新更新,我们可以轻松实现上述要求。

    这是演示link

    Map<MarkerId, Marker> _markers = <MarkerId, Marker>{};
    int _markerIdCounter = 0;
    Completer<GoogleMapController> _mapController = Completer();
    
    Container(
        width: MediaQuery.of(context).size.width,
        height: MediaQuery.of(context).size.height,
        child: GoogleMap(
          markers: Set<Marker>.of(_markers.values),
          onMapCreated: _onMapCreated,
          initialCameraPosition: CameraPosition(
            target: Constants.LOCATION_SRI_LANKA,
            zoom: 12.0,
          ),
          myLocationEnabled: true,
          onCameraMove: (CameraPosition position) {
            if(_markers.length > 0) {
              MarkerId markerId = MarkerId(_markerIdVal());
              Marker marker = _markers[markerId];
              Marker updatedMarker = marker.copyWith(
                positionParam: position.target,
              );
    
              setState(() {
                _markers[markerId] = updatedMarker;
              });
            }
          },
        ),
      )
    
    void _onMapCreated(GoogleMapController controller) async {
      _mapController.complete(controller);
      if ([INITIAL_LOCATION] != null) {
        MarkerId markerId = MarkerId(_markerIdVal());
        LatLng position = [INITIAL_LOCATION];
        Marker marker = Marker(
          markerId: markerId,
          position: position,
          draggable: false,
        );
        setState(() {
          _markers[markerId] = marker;
        });
    
        Future.delayed(Duration(seconds: 1), () async {
          GoogleMapController controller = await _mapController.future;
          controller.animateCamera(
            CameraUpdate.newCameraPosition(
              CameraPosition(
                target: position,
                zoom: 17.0,
              ),
            ),
          );
        });
      }
    }
    
    String _markerIdVal({bool increment = false}) {
      String val = 'marker_id_$_markerIdCounter';
      if (increment) _markerIdCounter++;
      return val;
    }
    

    【讨论】:

    • 这里的 INITIAL_LOCATION 是什么?
    • @JonStark 应用首次启动时,地图将从 INITIAL_LOCATION 开始,然后继续更新用户位置。
    • @PasanRandulaEramusugoda 不错的解决方案,但是 google_maps_flutter: ^0.4.0 的功能是什么,它可以将标记放在谷歌地图的中心
    【解决方案2】:

    这是基于@Joe 的答案,但它的引脚位置更准确,不需要其他类:

    double mapWidth = MediaQuery.of(context).size.width;
    double mapHeight = MediaQuery.of(context).size.height - 215;
    double iconSize = 40.0;
    
    return new Stack(
        alignment: Alignment(0.0, 0.0),
        children: <Widget>[
          new Container(
            width: mapWidth,
            height: mapHeight,
            child: _googleMap
          ),
          new Positioned(
            top: (mapHeight - iconSize)/ 2,
            right: (mapWidth - iconSize)/ 2,
            child: new Icon(Icons.person_pin_circle, size: iconSize),
          )
      ]);
    

    当用户更新位置时,此解决方案不需要重新绘制整个屏幕(没有 setState 调用)。你不会看到那个奇怪的标记“运动”。

    【讨论】:

    • 这不是正确的地方节目。 (mapHeight - 100)/ 2, 现在是正确的地方
    • 这个解决方案对我来说有点偏离中心。按照乔的回答对齐中心效果很好。
    • 那么如何知道标记的坐标呢?
    【解决方案3】:

    正确的答案是在地图上使用Stack 和覆盖标记图钉。如果您尝试使用 GoogleMaps 标记属性在地图上放置标记,则必须更新 CameraMove 上的标记位置并调用 setState,这会增加重绘制造商的延迟。

    比较两种方法:

    class StoreLocationMap extends StatefulWidget {
      final Coordinate userLocation;
      const StoreLocationMap({Key? key, required this.userLocation})
          : super(key: key);
    
      @override
      _StoreLocationMapState createState() => _StoreLocationMapState();
    }
    
    class _StoreLocationMapState extends State<StoreLocationMap> {
      final List<Marker> _markers = [];
      @override
      Widget build(BuildContext context) {
        return Stack(
          alignment: Alignment.center,
          children: [
            GoogleMap(
              initialCameraPosition: CameraPosition(
                  target: LatLng(
                      widget.userLocation.latitude, widget.userLocation.longitude),
                  zoom: 14),
    
            
              markers: _markers.toSet(),
            
              onMapCreated: (controller) {
                final marker = Marker(
                  markerId: MarkerId('0'),
                  position: LatLng(
                      widget.userLocation.latitude, widget.userLocation.longitude),
                  
                );
    
                _markers.add(marker);
              },
              onCameraMove: (position) {
                setState(() {
                  _markers.first =
                      _markers.first.copyWith(positionParam: position.target);
                });
              },
            ),
            Image.asset(
              'assets/images/delivery-area-start-pin.png',
              frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
                return Transform.translate(
                  offset: const Offset(8, -37),
                  child: child,
                );
              },
            )
          ],
        );
      }
    }
    

    由于我的自定义标记有阴影且不对称,我使用Transform 小部件将自定义标记转换为指向正确的位置。

    如何获取地图中心坐标?还是中锋位置?

    用户onCameraMove获取地图中心位置:

    onCameraMove: (position) {
                print(position.target);
              },
    

    【讨论】:

      【解决方案4】:

      可以使用堆栈。代码如下所示。

      Stack(
      children: <Widget>[
      GoogleMap(
      onMapCreated: _onMapCreated,
      ),
      InfoView()                  
       ],)
      

      InfoView 是

      class InfoView extends State<AppPage> {
          const InfoView({
              Key key,
              })  : super(key: key);
      
         @override
          Widget build(BuildContext context) {
          return new Align(
                  alignment: Alignment.center,
                  child: new Icon(Icons.person_pin_circle, size: 40.0),
      
              );
          }
      }
      

      那么 _onMapCreated 就是

      void _onMapCreated(GoogleMapController controller) {
              setState(() {
              mapController = controller;
                  mapController.animateCamera(CameraUpdate.newCameraPosition(
                          CameraPosition(
                          bearing: 270.0,
                          target: LatLng(lattitude, longitude),
                          tilt: 30.0,
                          zoom: 17.0,
                          ),
                      ));
              });
          }
          }
      

      如果您想以一种简单的方式重叠多个子项,例如有一些文本和一个图像,覆盖有渐变和一个附加到底部的按钮,则此堆栈类很有用。

      【讨论】:

        【解决方案5】:

        我推荐你试试这个新的 Flutter 包https://pub.dev/packages/flutter_animarker

        【讨论】:

          【解决方案6】:

          使用 Stack 和 IgnorePointer 忽略小部件上的触摸

          Stack(
            children: <Widget>[
              GoogleMap(
                ....
              ),
              Center(
               child: IgnorePointer(
                 child: ...
               )
              )               
            ]
          )
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2014-03-16
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-09-01
            • 1970-01-01
            相关资源
            最近更新 更多