Flutter 中的 Google 地图相机位置更新问题

问题描述 投票:0回答:4

我正在使用 Flutter 构建一个基于地图的应用程序。所以我使用谷歌地图包,一切正常。但是,我尝试添加一个 FloatingActionButton 以将地图重新定位到我的位置,但在这里,我遇到了问题。首先,地图没有重新定位到我的位置,其次,我收到了可怕的红色错误。这是代码、flutter doctor 和错误代码。

我的代码:

import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:provider/provider.dart';
import 'package:spotycar/providers/location_service.dart';

import '../../models/user_location.dart';

class MapWidget extends StatefulWidget {
  MapWidget({@required Key key}) : super(key: key);

  @override
  _MapWidgetState createState() => _MapWidgetState();
}

var locationClicked = false;

class _MapWidgetState extends State<MapWidget> {
  @override
  Widget build(BuildContext context) {
    CameraUpdate cameraUpdate;
    GoogleMapController mapController;
    var location = Provider.of<UserLocation>(context);
    final provider = Provider.of<LocationService>(context);
    final double _zoom = 17.0;
    final double _tilt = 37.0;
    var _coord;

    if (provider.loadedLocation) {
      _coord = LatLng(location.latitude, location.longitude);
      cameraUpdate = CameraUpdate.newCameraPosition(CameraPosition(
        target: _coord,
        bearing: location.heading,
        zoom: _zoom,
        tilt: _tilt,
      ));
    }

    if (locationClicked == true) {
      mapController.moveCamera(
        CameraUpdate.newCameraPosition(
          CameraPosition(
            target: _coord,
            bearing: location.heading,
            zoom: _zoom,
            tilt: _tilt,
          ),
        ),
      );
      setState(() {
        locationClicked = false;
      });
    }

    return Scaffold(
      body: !provider.loadedLocation
          ? Center(
              child: CircularProgressIndicator(
                valueColor: AlwaysStoppedAnimation<Color>(Colors.purple),
              ),
            )
          : GoogleMap(
              onMapCreated: (GoogleMapController controller) {
                mapController = controller;
                mapController.animateCamera(cameraUpdate);
              },
              myLocationEnabled: true,
              myLocationButtonEnabled: false,
              zoomControlsEnabled: false,
              initialCameraPosition: CameraPosition(
                target: _coord,
                zoom: _zoom,
                tilt: _tilt,
              ),
              rotateGesturesEnabled: true,
            ),
    );
  }
}

class LocationRechercheWidget extends StatefulWidget {
  @override
  _LocationRechercheWidgetState createState() =>
      _LocationRechercheWidgetState();
}

class _LocationRechercheWidgetState extends State<LocationRechercheWidget> {
  @override
  Widget build(BuildContext context) {
    return FloatingActionButton(
      child: Icon(
        Icons.location_searching,
        color: Colors.purple,
        size: 25,
      ),
      backgroundColor: Colors.white,
      onPressed: () {
        setState(() {
          locationClicked = true;
        });
      },
    );
  }
}

我的颤振医生:

[√] Flutter (Channel master, 1.20.0-3.0.pre.124, on Microsoft Windows [version 10.0.18362.900], locale fr-FR)
    • Flutter version 1.20.0-3.0.pre.124 at C:\flutter
    • Framework revision ec3368ae45 (2 days ago), 2020-07-02 01:58:01 -0400
    • Engine revision 65ac8be350
    • Dart version 2.9.0 (build 2.9.0-20.0.dev f8ff12008e)

 
[√] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
    • Android SDK at C:\Users\adrie\AppData\Local\Android\sdk
    • Platform android-29, build-tools 29.0.2
    • Java binary at: C:\Program Files\Android\Android Studio1310\jre\bin\java
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04)
    • All Android licenses accepted.

[√] Android Studio (version 3.6)
    • Android Studio at C:\Program Files\Android\Android Studio1310
    • Flutter plugin version 45.1.1
    • Dart plugin version 192.7761
    • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04)

[√] VS Code (version 1.46.1)
    • VS Code at C:\Users\adrie\AppData\Local\Programs\Microsoft VS Code
    • Flutter extension version 3.12.1

[√] Connected device (1 available)
    • Mi Note 10 (mobile) • 53bd04cc • android-arm64 • Android 10 (API 29)

• No issues found!

当我点击 FloatingActionButton 时遇到的错误:

═╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
The following NoSuchMethodError was thrown building MapWidget-[#2721f](dirty, dependencies:
[InheritedProvider<UserLocation>, InheritedProvider<LocationService>], state:
_MapWidgetState#50617):
The method 'moveCamera' was called on null.
Receiver: null
Tried calling: moveCamera(Instance of 'CameraUpdate')
The relevant error-causing widget was:
  MapWidget-[#2721f]
  
lib\screen\map_screen.dart:20
When the exception was thrown, this was the stack:
#0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:51:5)
#1      _MapWidgetState.build 
package:spotycar/…/map_screen/map_widget.dart:39
#2      StatefulElement.build 
package:flutter/…/widgets/framework.dart:4663
#3      ComponentElement.performRebuild 
package:flutter/…/widgets/framework.dart:4546
#4      StatefulElement.performRebuild 
package:flutter/…/widgets/framework.dart:4719
#5      Element.rebuild 
package:flutter/…/widgets/framework.dart:4262
#6      BuildOwner.buildScope 
package:flutter/…/widgets/framework.dart:2667
#7      WidgetsBinding.drawFrame 
package:flutter/…/widgets/binding.dart:866
#8      RendererBinding._handlePersistentFrameCallback 
package:flutter/…/rendering/binding.dart:286
#9      SchedulerBinding._invokeFrameCallback 
package:flutter/…/scheduler/binding.dart:1115
#10     SchedulerBinding.handleDrawFrame 
package:flutter/…/scheduler/binding.dart:1054
#11     SchedulerBinding._handleDrawFrame 
package:flutter/…/scheduler/binding.dart:970
#15     _invoke  (dart:ui/hooks.dart:253:10)
#16     _drawFrame  (dart:ui/hooks.dart:211:3)
(elided 3 frames from dart:async)
google-maps flutter google-maps-flutter
4个回答
21
投票

要解决此问题,您需要使用 Completer 而不是简单的 GoogleMapController。

当你实例化它时:

Completer<GoogleMapController> _controller = Completer();

然后在 GoogleMap 小部件内的

onMapCreated
方法中:

onMapCreated: (GoogleMapController controller) {
      _controller.complete(controller);
      ...
},

每当您想更改相机位置时:

Future<void> moveCamera() async {
  final GoogleMapController controller = await _controller.future;
  controller.moveCamera(CameraUpdate.newCameraPosition(CameraPosition(
    target: LatLong(..., ...),
    zoom: ...,
  )));
}

你应该表现得很好!


1
投票

对于那些在 Flutter 中使用 FlutterMap 或 MapBox 的人

上面的答案是正确的,但我要补充一件事,这对我来说也是一个大问题。 如何根据用户缩放保持缩放级别因为当您监听当前位置变化并根据它更新相机位置时,缩放级别也会选择您一开始提供的缩放级别。


例如:您在开始时提供缩放级别13,然后将屏幕缩放到16,然后当相机位置更新时,它会再次将您带到缩放级别13,并且每秒都会重复,这真的很烦人, 因此您必须动态提供缩放级别,它将根据用户缩放级别而变化。


首先收听位置流:

location.onLocationChanged.listen((event) {
final newLatLng = LatLng(event.latitude!, event.longitude!);
// Use mapController to access the move method
// move() method is used for the camera position changing e.g: move(LatLng center,   double zoom)
mapController.move(newLatLng , 13);  // this will set the zoom level static to 13
// but we want it to be dynamic according to the user zoom level,
// so then use the mapController.zoom property will dynamically adjust your zoom level
 mapController.move(newLatLng , mapController.zoom); 
});

0
投票

我遇到了这个问题,我有 Vayhuit 使用的确切代码。我的密码会更新,但摄像头会到达我上次搜索的位置。为了解决这个问题我必须改变

static final CameraPosition _location = CameraPosition(
target: LatLng(lat!, lng!),
zoom: 15,
);

我有一个初始化状态,所以我创建了一个

late CameraPosition _location;

然后

 getLocation() {
_location = CameraPosition(
  target: LatLng(lat!, lng!),
  zoom: 15,
     );
   }

然后我刚刚添加了 getLocation();到初始状态。似乎现在可以工作了。


0
投票

我遇到了同样的异常,我必须根据相机约束调整初始中心

喜欢,

initialZoom: 2.3,
cameraConstraint: CameraConstraint.contain(
   bounds: LatLngBounds(
     const LatLng(-90, -180),
     const LatLng(90, 180),
   ),
)

              
              

对于上述边界,它与 2.3 的初始缩放完美配合,如果我小于此值,它会再次抛出 MapCamera,不在cameraConstraint 错误内。

这是我的完整代码

FlutterMap(
  options: MapOptions(
    minZoom: 1,
    maxZoom: 19,
    initialCenter: const LatLng(0, 0),
    initialZoom: 2.3,
    cameraConstraint: CameraConstraint.contain(
    bounds: LatLngBounds(
     const LatLng(-90, -180),
     const LatLng(90, 180),
    ),
   ),
   onTap: (tapPosition, point)  {
     //Tap logic
   },
   onPointerHover: (event, point) {
     //Hover logic  
   },
  ),
  mapController: mapProvider.mapController,
  children: [
   TileLayer(
     urlTemplate:
     'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
      userAgentPackageName: 'com.example.app',
      tileProvider: CancellableNetworkTileProvider(),
     ),
     //other layers
   ]
), 
© www.soinside.com 2019 - 2024. All rights reserved.