首页 > 解决方案 > Flutter Google Maps - 将相机移动到当前位置

问题描述

在我的 Flutter 项目中,我使用 Google Maps 插件在应用程序中显示地图。在地图上,我想显示用户的当前位置,为此我使用 Geolocator。

当地图加载时,它将加载到一个静态点,当用户拒绝位置权限时,用户仍然可以在没有位置的情况下使用地图。当用户接受我想将相机移动到用户当前位置的权限时。

我在下面的代码中实现了上述功能,但我也收到以下错误,我不知道如何解决它。

import 'package:flutter/material.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'dart:typed_data';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:hvd_test/styling/colors.dart';
import 'package:hvd_test/models/navigation.dart';
import 'package:hvd_test/models/markers.dart';

// This page shows a Google Map plugin with all stations (HvD and Total). The markers are pulled from a Firebase database.

class StationsMap extends StatefulWidget {
  @override
  _StationsMap createState() => _StationsMap();
}

class _StationsMap extends State<StationsMap> {
  bool _isLocationGranted = false;

  var currentLocation;

  GoogleMapController mapController;

  Map<MarkerId, Marker> markers = <MarkerId, Marker>{};

// Below function initiates all HvD stations and shows them as markers on the map. It also generates a Bottom Sheet for each location with corresponding information.

  void initMarkerHvD(specify, specifyId) async {
    var markerIdVal = specifyId;
    final Uint8List markerHvD =
        await getBytesFromAsset('images/Pin-HvD.JPG', 70);
    final MarkerId markerId = MarkerId(markerIdVal);
    final Marker marker = Marker(
      markerId: markerId,
      onTap: () {
        showModalBottomSheet(
            context: context,
            builder: (context) => SingleChildScrollView(
                  child: Container(
                    padding: EdgeInsets.only(
                        bottom: MediaQuery.of(context).viewInsets.bottom),
                    child: Container(
                      color: Color(0xff757575),
                      child: Container(
                        padding: EdgeInsets.all(20.0),
                        decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.only(
                                topLeft: const Radius.circular(20.0),
                                topRight: const Radius.circular(20.0))),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: [
                            Text(
                              specify['stationName'],
                              style: TextStyle(
                                  color: PaletteBlue.hvdblue,
                                  fontWeight: FontWeight.bold,
                                  fontSize: 16),
                              textAlign: TextAlign.center,
                            ),
                            SizedBox(height: 10),
                            Text(specify['stationAddress']),
                            Text(specify['stationZIP'] +
                                ' ' +
                                specify['stationCity']),
                            SizedBox(height: 20),
                            ElevatedButton(
                                child: Text(
                                  'Navigeer naar locatie',
                                  style: TextStyle(
                                    color: Colors.white,
                                  ),
                                ),
                                style: ButtonStyle(
                                    backgroundColor: MaterialStateProperty.all(
                                        PaletteOrange.hvdorange)),
                                onPressed: () {
                                  MapUtils.openMap(
                                      specify['stationLocation'].latitude,
                                      specify['stationLocation'].longitude);
                                }),
                          ],
                        ),
                      ),
                    ),
                  ),
                ));
      },
      position: LatLng(specify['stationLocation'].latitude,
          specify['stationLocation'].longitude),
      infoWindow: InfoWindow(),
      icon: BitmapDescriptor.fromBytes(markerHvD),
    );
    setState(() {
      markers[markerId] = marker;
    });
  }

// Below function initiates all Total stations and shows them as markers on the map. It also generates a Bottom Sheet for each location with corresponding information.

  void initMarkerTotal(specify, specifyId) async {
    var markerIdVal = specifyId;
    final Uint8List markerTotal =
        await getBytesFromAsset('images/Pin-Total.JPG', 70);
    final MarkerId markerId = MarkerId(markerIdVal);
    final Marker marker = Marker(
      markerId: markerId,
      onTap: () {
        showModalBottomSheet(
            context: context,
            builder: (context) => SingleChildScrollView(
                  child: Container(
                    padding: EdgeInsets.only(
                        bottom: MediaQuery.of(context).viewInsets.bottom),
                    child: Container(
                      color: Color(0xff757575),
                      child: Container(
                        padding: EdgeInsets.all(20.0),
                        decoration: BoxDecoration(
                            color: Colors.white,
                            borderRadius: BorderRadius.only(
                                topLeft: const Radius.circular(20.0),
                                topRight: const Radius.circular(20.0))),
                        child: Column(
                          crossAxisAlignment: CrossAxisAlignment.stretch,
                          children: [
                            Text(
                              specify['stationName'],
                              style: TextStyle(
                                  color: PaletteBlue.hvdblue,
                                  fontWeight: FontWeight.bold,
                                  fontSize: 16),
                              textAlign: TextAlign.center,
                            ),
                            SizedBox(height: 10),
                            Text(specify['stationAddress']),
                            Text(specify['stationZIP'] +
                                ' ' +
                                specify['stationCity']),
                            SizedBox(height: 20),
                            ElevatedButton(
                                child: Text(
                                  'Navigeer naar locatie',
                                  style: TextStyle(
                                    color: Colors.white,
                                  ),
                                ),
                                style: ButtonStyle(
                                    backgroundColor: MaterialStateProperty.all(
                                        PaletteOrange.hvdorange)),
                                onPressed: () {
                                  MapUtils.openMap(
                                      specify['stationLocation'].latitude,
                                      specify['stationLocation'].longitude);
                                }),
                          ],
                        ),
                      ),
                    ),
                  ),
                ));
      },
      position: LatLng(specify['stationLocation'].latitude,
          specify['stationLocation'].longitude),
      infoWindow: InfoWindow(),
      icon: BitmapDescriptor.fromBytes(markerTotal),
    );
    setState(() {
      markers[markerId] = marker;
    });
  }

// Below functions pulls all HvD markers from the database.

  getMarkerDataHvD() async {
    FirebaseFirestore.instance
        .collection('hvd-stations')
        .get()
        .then((myMarkers) {
      if (myMarkers.docs.isNotEmpty) {
        for (int i = 0; i < myMarkers.docs.length; i++) {
          initMarkerHvD(myMarkers.docs[i].data(), myMarkers.docs[i].id);
        }
      }
    });
  }

// Below function pulls all Total markers from the database.

  getMarkerDataTotal() async {
    FirebaseFirestore.instance
        .collection('total-stations')
        .get()
        .then((myMarkers) {
      if (myMarkers.docs.isNotEmpty) {
        for (int i = 0; i < myMarkers.docs.length; i++) {
          initMarkerTotal(myMarkers.docs[i].data(), myMarkers.docs[i].id);
        }
      }
    });
  }

// Below function initiates all previous functions on the page. This happens when the user navigates to the page.

  void initState() {
    getMarkerDataHvD();
    getMarkerDataTotal();
    super.initState();
    Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high)
        .then((currloc) {
      setState(() {
        currentLocation = currloc;
        _isLocationGranted = true;
      });
      mapController.moveCamera(CameraUpdate.newLatLng(LatLng(currentLocation.latitude, currentLocation.longitude))) as CameraPosition;
    });
  }

  CameraPosition _initialCameraPosition =
      CameraPosition(target: const LatLng(51.9244201, 4.4777325), zoom: 12);
  

// Below function is used to display all previous functions to the page.

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Stack(
          children: <Widget>[
            GoogleMap(
              onMapCreated: onMapCreated,
              markers: Set<Marker>.of(markers.values),
              gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>[
                new Factory<OneSequenceGestureRecognizer>(
                  () => new EagerGestureRecognizer(),
                ),
              ].toSet(),
              mapToolbarEnabled: false,
              zoomGesturesEnabled: true,
              zoomControlsEnabled: false,
              scrollGesturesEnabled: true,
              myLocationEnabled: _isLocationGranted,
              myLocationButtonEnabled: true,
              initialCameraPosition: _initialCameraPosition,
            ),
          ],
        ),
      ),
    );
  }

  onMapCreated(GoogleMapController controller) {
    mapController = controller;
  }
}

我得到的错误是这样的:

E/flutter ( 7769): [ERROR:flutter/lib/ui/ui_dart_state.cc(199)] Unhandled Exception: type 'Future<void>' is not a subtype of type 'CameraPosition' in type cast
E/flutter ( 7769): #0      _StationsMap.initState.<anonymous closure>
E/flutter ( 7769): #1      _rootRunUnary (dart:async/zone.dart:1362:47)
E/flutter ( 7769): #2      _CustomZone.runUnary (dart:async/zone.dart:1265:19)
E/flutter ( 7769): <asynchronous suspension>

有人可以给我一些帮助吗?

标签: androidiosfluttergoogle-mapsgeolocation

解决方案


Thanks to @Andy I solved the problem. I removed "as CameraPosition" from the code and then the function worked. I also implemented a zoom by using:

mapController.animateCamera(CameraUpdate.newLatLngZoom(LatLng(currentLocation.latitude, currentLocation.longitude), 14));

推荐阅读