【问题标题】:How to add markers to a flutter google map after the map has been created and change the camera position?创建地图后如何向颤动的谷歌地图添加标记并更改相机位置?
【发布时间】:2022-01-18 16:47:29
【问题描述】:

我是 Flutter 的新手,我使用 flutter_google_maps 包创建了一个谷歌地图。

我的父小部件中有以下代码,

SizedBox(
    child: _showFindHouseModal
    ? FutureBuilder<Address?>(
        future: _locationDataFuture,
        builder: (context, snapshot) {

            if (snapshot.hasData) {
                return Map(
                    initialLatitude: _userLocation.latitude!.toDouble(),
                    initialLongitude: _userLocation.longitude!.toDouble(),
                    markers: const [],
                );
            }
        },
    )
    : FutureBuilder<Address?>(
        future: _showFindHouseModal,
        builder: (context, snapshot) {
            if (snapshot.hasData) {
                return Map(         // <---------------------------------------- This one is the problem
                    initialLongitude: _userLocation.latitude!.toDouble(),
                    initialLatitude: _userLocation.latitude!.toDouble(),
                    markers: [
                        Marker(
                            markerId: MarkerId('${_housesList.first.id}'),
                            position: LatLng(_housesList.first.houseLatitude, _housesList.first.houseLongitude),
                        ),
                    ],
                );
            }
        }),
),

在上面的代码中,你可以看到我使用的是三元运算符。如果_showFindHouseModal 为真,则构建Map 小部件。如果不正确,则将构建相同的 Map 小部件,但带有额外的标记。问题是,我转发的那些附加标记没有呈现在屏幕上。

不过,我想我找到了问题所在。它在子小部件中。 (就是我找不到解决问题的办法)

让我展示子小部件的代码。

class Map extends StatefulWidget {

  final List<Marker> markers;
  final double initialLatitude;
  final double initialLongitude;

  const Map({
    Key? key,
    required this.initialLatitude,
    required this.initialLongitude,
    required this.markers, // Todo: Make the default to an empty value
  }) : super(key: key);

  @override
  State<Map> createState() => MapState();
}

class MapState extends State<Map> {
  late final CameraPosition _initialCameraPosition;

  late final Set<Marker> _markers = {};

  final Completer<GoogleMapController> _controller = Completer();

  @override
  void initState() {
    super.initState();

    _initialCameraPosition = CameraPosition(
      target: LatLng(widget.initialLatitude, widget.initialLongitude),
      zoom: 12,
    );
  }

  @override
  Widget build(BuildContext context) {
    return GoogleMap(
      mapType: MapType.normal,
      initialCameraPosition: _initialCameraPosition,
      markers: _markers,
      onMapCreated: (GoogleMapController controller) {
        _controller.complete(controller);

        setState(
          () {
            _markers.addAll(widget.markers);  <--------- This is the problem I think
            _markers.add(
              Marker(
                markerId: const MarkerId('user-marker'),
                position: LatLng(widget.initialLatitude, widget.initialLongitude),
              ),
            );
          },
        );
      },
    );
  }
}

正如我在代码中指出的那样,我认为问题在于,在子小部件内部,这些标记被添加到 onMapCreated 属性下。由于地图已经在第一个FutureBuilder 中创建,因此这些标记由于某种原因没有添加到地图中。我不知道如何从第二个FutureBuilder 添加新标记。我添加的标记没有通过。

有人可以帮忙吗?我一直在努力寻找 6 个小时左右的方法,但无法成功。

【问题讨论】:

    标签: flutter google-maps google-maps-markers flutter-futurebuilder flutter-state


    【解决方案1】:

    试试这个,改变你分配标记的行

      markers: _markers
    

    沿着这条线

    markers: Set<Marker>.of(_markers.values),
    

    【讨论】:

      【解决方案2】:

      1- 可能性不大,但也许您可以更改标记: const [] 行仅 [] 不带 cons 关键字。

      2- 这比第一个更有可能,尝试用其中一个作为未来的构建器,使用不同的小部件(如 SizedBox)或给其中一个唯一的密钥。 (但我建议第一种方法:条件?FutureBuilder:SizedBox(child: FutureBuilder))因为,您的问题可能与小部件树渲染有关。如果这解决了您的问题,我可以添加一个关于该问题的 youtube 链接,您可以理解我要指出的含义。

      3- 相机位置,在相机创建函数调用后,在初始化googleMapsController的帮助下,您可以使用googleMapsController.animateCamera()函数更改相机位置、相机缩放和其他一些东西,

      示例; googleMapsController.animateCamera(CameraUpdate.newLatLng(latLng)) 会将谷歌地图视图更改为新的经纬度点。所以我建议,不要为此使用future builder,只需在初始化后为您的相机设置动画,您可以在获取位置之前使用IgnorePointer 覆盖您的地图小部件,这样您可以确保动画不会阻止用户交互。

      【讨论】:

        【解决方案3】:

        这可能对你有帮助

        bool mapToggle = false;
          Position currentLocation;
          GoogleMapController mapController;
          GoogleMap googleMap;
          var ads = [];
          Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
          MarkerId selectedMarker;
          LatLng markerPosition;
          bool clientToggle = false;
          @override
          void initState() {
            super.initState();
            // GeolocationStatus geolocationStatus  = await Geolocator.checkGeolocationPermissionStatus();
            // Geolocator.checkPermission();
            // Geolocator.getServiceStatusStream();
            Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
                .then((currloc) {
              setState(() {
                currentLocation = currloc;
                mapToggle = true;
                populateClient();
              });
            });
          }
        
        
        
         @override
          void dispose() {
            super.dispose();
          }
        
          populateClient() {
            kfirestore.collection('marks').get().then((value) {
              if (value.docs.isNotEmpty) {
                setState(() {
                  clientToggle = true;
                });
                for (int i = 0; i < value.docs.length; i++) {
                  ads.add(value.docs[i].data());
                  initMarker(value.docs[i].data(), value.docs[i].id);
                  var _distanceBetweenLastTwoLocations = Geolocator.distanceBetween(
                    value.docs[i].data()['location'].latitude,
                    value.docs[i].data()['location'].longitude,
                    currentLocation.latitude,
                    currentLocation.longitude,
                  );
                  print("bairshiluud:" + _distanceBetweenLastTwoLocations.toString());
                  if (_distanceBetweenLastTwoLocations < 100) {
                    SuccessDialog(
                      title: "Таны байршилтай ойр сурталчилгаа",
                      titleColor: Colors.green,
                      description: value.docs[i].data()['adName'],
                    );
                  } else {
                    SuccessDialog(
                      title: "Таны байршилтай ойр сурталчилгаа",
                      titleColor: Colors.green,
                      description: "Таны байршилд ойр сурталчилгаа олдсонгүй.",
                    );
                  }
                }
              }
            });
          }
        
          void initMarker(specify, specifyId) async {
            var markerIdVal = specifyId;
            final MarkerId markerId = MarkerId(markerIdVal);
            final Marker marker = Marker(
              markerId: markerId,
              position: LatLng(
                specify['location'].latitude,
                specify['location'].longitude,
              ),
              infoWindow: InfoWindow(title: specify['adName'], snippet: "Сурталчилгаа"),
              icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRose),
            );
            setState(() {
              markers[markerId] = marker;
            });
          }
        
        Container(
                          height: MediaQuery.of(context).size.height - 80,
                          width: double.infinity,
                          child: mapToggle
                              ? GoogleMap(
                                  mapType: MapType.hybrid,
                                  compassEnabled: true,
                                  onMapCreated: onMapCreated,
                                  buildingsEnabled: true,
                                  myLocationButtonEnabled: true,
                                  myLocationEnabled: true,
                                  rotateGesturesEnabled: true,
                                  zoomControlsEnabled: true,
                                  zoomGesturesEnabled: true,
                                  indoorViewEnabled: true,
                                  mapToolbarEnabled: true,
                                  tiltGesturesEnabled: true,
                                  scrollGesturesEnabled: true,
                                  initialCameraPosition: CameraPosition(
                                    target: LatLng(currentLocation.latitude,
                                        currentLocation.longitude),
                                    zoom: 15,
                                  ),
                                  // circles: circles,
                                  markers: Set<Marker>.of(markers.values),
                                )
                              : Center(
                                  child: Text("Loading"),
                                ),
                        ),
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-09-23
        • 2018-09-17
        • 2020-10-23
        • 2019-10-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-15
        相关资源
        最近更新 更多