You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FlutterFlow添加自定义Google Maps组件报错求助

自定义Google Maps组件在FlutterFlow中报错求助

我是纯编程新手,完全不懂编程相关知识。现在用FlutterFlow开发应用,添加自定义Google Maps组件时遇到问题,多行代码出现相同的两个错误。

以下是我使用的自定义组件代码:

// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'dart:math';
import 'package:google_maps_widget/google_maps_widget.dart';

class GMaps extends StatefulWidget {
  const GMaps({
    Key? key,
    this.width,
    this.height,
  }) : super(key: key);

  final double? width;
  final double? height;

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

class _GMapsState extends State<GMaps> {
  final mapsWidgetController = GlobalKey<GoogleMapsWidgetState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: Column(
            children: [
              Expanded(
                child: GoogleMapsWidget(
                  apiKey: "XXXXX",
                  key: mapsWidgetController,
                  sourceLatLng: LatLng(
                    40.484000837597925,
                    -3.369978368282318,
                  ),
                  destinationLatLng: LatLng(
                    40.48017307700204,
                    -3.3618026599287987,
                  ),

                  ///////////////////////////////////////////////////////
                  //////////////    OPTIONAL PARAMETERS    //////////////
                  ///////////////////////////////////////////////////////

                  routeWidth: 2,
                  sourceMarkerIconInfo: MarkerIconInfo(
                    infoWindowTitle: "This is source name",
                    onTapInfoWindow: (_) {
                      print("Tapped on source info window");
                    },
                    assetPath: "assets/images/house-marker-icon.png",
                  ),
                  destinationMarkerIconInfo: MarkerIconInfo(
                    assetPath: "assets/images/restaurant-marker-icon.png",
                  ),
                  driverMarkerIconInfo: MarkerIconInfo(
                    infoWindowTitle: "Alex",
                    assetPath: "assets/images/driver-marker-icon.png",
                    onTapMarker: (currentLocation) {
                      print("Driver is currently at $currentLocation");
                    },
                    assetMarkerSize: Size.square(125),
                    rotation: 90,
                  ),
                  onPolylineUpdate: (p) {
                    print("Polyline updated: ${p.points}");
                  },
                  updatePolylinesOnDriverLocUpdate: true,
                  // mock stream
                  driverCoordinatesStream: Stream.periodic(
                    Duration(milliseconds: 500),
                    (i) => LatLng(
                      40.47747872288886 + i / 10000,
                      -3.368043154478073 - i / 10000,
                    ),
                  ),
                  totalTimeCallback: (time) => print(time),
                  totalDistanceCallback: (distance) => print(distance),
                ),
              ),
              // demonstrates how to interact with the controller
              Padding(
                padding: const EdgeInsets.all(10),
                child: Row(
                  children: [
                    Expanded(
                      child: ElevatedButton(
                        onPressed: () {
                          mapsWidgetController.currentState!.setSourceLatLng(
                            LatLng(
                              40.484000837597925 * (Random().nextDouble()),
                              -3.369978368282318,
                            ),
                          );
                        },
                        child: Text('Update source'),
                      ),
                    ),
                    const SizedBox(width: 10),
                    Expanded(
                      child: ElevatedButton(
                        onPressed: () async {
                          final googleMapsCon = await mapsWidgetController
                              .currentState!
                              .getGoogleMapsController();
                          googleMapsCon.showMarkerInfoWindow(
                            MarkerIconInfo.sourceMarkerId,
                          );
                        },
                        child: Text('Show source info'),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // can create a controller, and call methods to update source loc,
  // destination loc, interact with the google maps controller to
  // show/hide markers programmatically etc.
  final mapsWidgetController = GlobalKey<GoogleMapsWidgetState>();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: SafeArea(
        child: Scaffold(
          body: Column(
            children: [
              Expanded(
                child: GoogleMapsWidget(
                  apiKey: "XXXXX",
                  key: mapsWidgetController,
                  sourceLatLng: LatLng(
                    40.484000837597925,
                    -3.369978368282318,
                  ),
                  destinationLatLng: LatLng(
                    40.48017307700204,
                    -3.3618026599287987,
                  ),

                  ///////////////////////////////////////////////////////
                  //////////////    OPTIONAL PARAMETERS    //////////////
                  ///////////////////////////////////////////////////////

                  routeWidth: 2,
                  sourceMarkerIconInfo: MarkerIconInfo(
                    infoWindowTitle: "This is source name",
                    onTapInfoWindow: (_) {
                      print("Tapped on source info window");
                    },
                    assetPath: "assets/images/house-marker-icon.png",
                  ),
                  destinationMarkerIconInfo: MarkerIconInfo(
                    assetPath: "assets/images/restaurant-marker-icon.png",
                  ),
                  driverMarkerIconInfo: MarkerIconInfo(
                    infoWindowTitle: "Alex",
                    assetPath: "assets/images/driver-marker-icon.png",
                    onTapMarker: (currentLocation) {
                      print("Driver is currently at $currentLocation");
                    },
                    assetMarkerSize: Size.square(125),
                    rotation: 90,
                  ),
                  onPolylineUpdate: (p) {
                    print("Polyline updated: ${p.points}");
                  },
                  updatePolylinesOnDriverLocUpdate: true,
                  // mock stream
                  driverCoordinatesStream: Stream.periodic(
                    Duration(milliseconds: 500),
                    (i) => LatLng(
                      40.47747872288886 + i / 10000,
                      -3.368043154478073 - i / 10000,
                    ),
                  ),
                  totalTimeCallback: (time) => print(time),
                  totalDistanceCallback: (distance) => print(distance),
                ),
              ),
              // demonstrates how to interact with the controller
              Padding(
                padding: const EdgeInsets.all(10),
                child: Row(
                  children: [
                    Expanded(
                      child: ElevatedButton(
                        onPressed: () {
                          mapsWidgetController.currentState!.setSourceLatLng(
                            LatLng(
                              40.484000837597925 * (Random().nextDouble()),
                              -3.369978368282318,
                            ),
                          );
                        },
                        child: Text('Update source'),
                      ),
                    ),
                    const SizedBox(width: 10),
                    Expanded(
                      child: ElevatedButton(
                        onPressed: () async {
                          final googleMapsCon = await mapsWidgetController
                              .currentState!
                              .getGoogleMapsController();
                          googleMapsCon.showMarkerInfoWindow(
                            MarkerIconInfo.sourceMarkerId,
                          );
                        },
                        child: Text('Show source info'),
                      ),
                    ),
                  ],
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

问题原因及修复方案

核心问题

  1. 重复的应用入口代码:FlutterFlow的自定义组件不需要main()函数和MyApp类,这些是独立Flutter应用的启动逻辑,保留会与FlutterFlow的框架冲突,导致报错。
  2. 错误的组件层级:自定义组件不应返回MaterialApp和Scaffold,因为FlutterFlow已经提供了完整的应用结构,嵌套这些组件会造成上下文冲突。
  3. 缺失必要导入:LatLng类来自google_maps_flutter包,原代码未导入,导致该类无法识别。

修复后的代码

// Automatic FlutterFlow imports
import '/backend/backend.dart';
import '/flutter_flow/flutter_flow_theme.dart';
import '/flutter_flow/flutter_flow_util.dart';
import '/custom_code/widgets/index.dart'; // Imports other custom widgets
import '/flutter_flow/custom_functions.dart'; // Imports custom functions
import 'package:flutter/material.dart';
// Begin custom widget code
// DO NOT REMOVE OR MODIFY THE CODE ABOVE!

import 'dart:math';
import 'package:google_maps_widget/google_maps_widget.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart'; // 导入LatLng所需的包

class GMaps extends StatefulWidget {
  const GMaps({
    Key? key,
    this.width,
    this.height,
  }) : super(key: key);

  final double? width;
  final double? height;

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

class _GMapsState extends State<GMaps> {
  final mapsWidgetController = GlobalKey<GoogleMapsWidgetState>();

  @override
  Widget build(BuildContext context) {
    // 使用给定的宽高包裹地图组件,适配FlutterFlow的布局系统
    return SizedBox(
      width: widget.width,
      height: widget.height,
      child: GoogleMapsWidget(
        apiKey: "XXXXX", // 替换为你的Google Maps API Key
        key: mapsWidgetController,
        sourceLatLng: const LatLng(
          40.484000837597925,
          -3.369978368282318,
        ),
        destinationLatLng: const LatLng(
          40.48017307700204,
          -3.3618026599287987,
        ),

        ///////////////////////////////////////////////////////
        //////////////    OPTIONAL PARAMETERS    //////////////
        ///////////////////////////////////////////////////////

        routeWidth: 2,
        sourceMarkerIconInfo: MarkerIconInfo(
          infoWindowTitle: "This is source name",
          onTapInfoWindow: (_) {
            print("Tapped on source info window");
          },
          assetPath: "assets/images/house-marker-icon.png",
        ),
        destinationMarkerIconInfo: MarkerIconInfo(
          assetPath: "assets/images/restaurant-marker-icon.png",
        ),
        driverMarkerIconInfo: MarkerIconInfo(
          infoWindowTitle: "Alex",
          assetPath: "assets/images/driver-marker-icon.png",
          onTapMarker: (currentLocation) {
            print("Driver is currently at $currentLocation");
          },
          assetMarkerSize: const Size.square(125),
          rotation: 90,
        ),
        onPolylineUpdate: (p) {
          print("Polyline updated: ${p.points}");
        },
        updatePolylinesOnDriverLocUpdate: true,
        // 模拟司机位置更新的流
        driverCoordinatesStream: Stream.periodic(
          const Duration(milliseconds: 500),
          (i) => LatLng(
            40.47747872288886 + i / 10000,
            -3.368043154478073 - i / 10000,
          ),
        ),
        totalTimeCallback: (time) => print(time),
        totalDistanceCallback: (distance) => print(distance),
      ),
    );
  }
}

额外注意事项

  • 确保在FlutterFlow项目的依赖中添加了google_maps_widget包,版本需与项目兼容。
  • 将代码中的"XXXXX"替换为你的Google Maps API Key,且该Key需启用Maps SDK for Android和iOS权限。
  • 确认代码中引用的图片资源已上传至FlutterFlow资产库,路径与代码一致。

内容的提问来源于stack exchange,提问作者H 722

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 06:42:09