修复谷歌地图标记在中心

时间:2018-12-06 13:31:04

标签: google-maps dart flutter

在我的Flutter应用中。我正在使用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中,我想知道如何赋予地图中心。

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

6 个答案:

答案 0 :(得分:3)

实际上,通过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;
}

答案 1 :(得分:3)

我建议您尝试使用这个新的Flutter软件包https://pub.dev/packages/flutter_animarker

答案 2 :(得分: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),
      )
  ]);

此解决方案不需要在用户更新位置时重新绘制整个Screen(无需setState调用)。您不会看到怪异的标记“运动”。

答案 3 :(得分:2)

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

比较两种方法:

enter image description here

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 :(得分:1)

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

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 :(得分:0)

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

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