自定义 Google 地图标记 Flutter

Custom Google Maps Marker Flutter

我在使用 flutter 的 GoogleMaps 项目中使用自定义标记时遇到问题。我在地图屏幕加载时收到此错误

发生异常。 LateError(LateInitializationError:字段 'myMarker' 尚未初始化。)

我试过不使用 late,它说 myMarker 必须初始化,所以我声明它为 late,然后在 initState 中初始化它。那没有用,所以我尝试使用可为空的 ? 并且也没有用。任何帮助,将不胜感激。 谢谢

import 'dart:async';
import 'dart:developer';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:location/location.dart';
import 'dart:math' as math;

import './main.dart' as main;
import './variables.dart' as variables;
import './methods.dart' as methods;
import './mapvariables.dart' as mapVar;
import './marker_information.dart' as markerInfo;

class MapScreen extends StatefulWidget {
  const MapScreen({Key? key}) : super(key: key);

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

class _MapScreenState extends State<MapScreen> {
  Completer<GoogleMapController> _controllerGoogleMap = Completer();
  late GoogleMapController newGoogleMapController;
  Position? currentPosition;
  var geoLocator = Geolocator();
  final double dcheck = 0.00014128694207108202;
  var location = new Location();
  late BitmapDescriptor myMarker;

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

  void setMarker() async {
    myMarker = await BitmapDescriptor.fromAssetImage(
        ImageConfiguration(), 'loginlogo.png');
  }

  checkpermission_location() async {
    var locationStatus = await Permission.location.status;
    print(locationStatus);

    if (!locationStatus.isGranted) {
      print("gr");
      print(await Permission.location.value);
      await Permission.location.request();
      checkpermission_location();
    }

    if (!locationStatus.isDenied) {
      print('de');
      await Permission.location.request();
      checkLocation();
    }
  }

  void checkClue(var x, var y, markerInfo.ClueLocation marker) {
    double distance = methods.distance(marker.lat, marker.long, x, y);
    log("distance: $distance");
    if ((distance < dcheck)) {
      variables.dialogVis = true;
      if ((variables.dialogVis) && (marker.compl == false)) {
        mapVar.showAlertDialog(context, marker);
        variables.dialogVis = false;
        marker.compl = true;
      }
    }
  }

  void checkLocation() {
    location.onLocationChanged.listen((LocationData currentLocation) {
      var lat = currentLocation.latitude;
      var long = currentLocation.longitude;
      checkClue(lat, long, markerInfo.newHamCollege);
      checkClue(lat, long, markerInfo.coeFen);
      checkClue(lat, long, markerInfo.mathematicalBridge);
      checkClue(lat, long, markerInfo.graveYard);
      checkClue(lat, long, markerInfo.archeologicalMuseum);
      checkClue(lat, long, markerInfo.addenbrokesHospital);
      checkClue(lat, long, markerInfo.stMarysBellTower);
      checkClue(lat, long, markerInfo.trinityStreet);
      checkClue(lat, long, markerInfo.viewOfTheBridgeOfSighs);
    });
  }

  //Initial camera position when maps first load
  static const _initalCameraPosition = CameraPosition(
    target: LatLng(52.2053, 0.1218),
    zoom: 11.5,
  );

  Marker makeMarker(markerInfo.ClueLocation marker) {
    return (Marker(
        markerId: MarkerId(marker.title),
        infoWindow: InfoWindow(title: marker.title),
        icon: myMarker,
        position: LatLng(marker.lat, marker.long),
        onTap: () {
          if (marker.compl) {
            mapVar.showAlertDialog(context, marker);
          }
        }));
  }

  //Google map widget
  @override
  Widget build(BuildContext context) {
    //Checks if mapAcess is true
    if (variables.mapAccess) {
      var currentlocation = location.getLocation();
      return Scaffold(
        body: GoogleMap(
          onMapCreated: (GoogleMapController controller) {
            controller.setMapStyle(mapVar.mapStyle);
            checkpermission_location();
            _controllerGoogleMap.complete(controller);
            newGoogleMapController = controller;
          },
          mapType: MapType.normal,
          myLocationButtonEnabled: true,
          zoomControlsEnabled: true,
          myLocationEnabled: true,
          zoomGesturesEnabled: true,
          markers: {
            //Markers located in the variables.dart file
            makeMarker(markerInfo.newHamCollege),
            makeMarker(markerInfo.coeFen),
            makeMarker(markerInfo.mathematicalBridge),
            makeMarker(markerInfo.graveYard),
            makeMarker(markerInfo.archeologicalMuseum),
            //6.??? Waiting for update from Konstantin
            makeMarker(markerInfo.addenbrokesHospital),
            makeMarker(markerInfo.stMarysBellTower),
            makeMarker(markerInfo.trinityStreet),
            makeMarker(markerInfo.viewOfTheBridgeOfSighs),
          },
          initialCameraPosition: _initalCameraPosition,
        ),
      );
    }
    //Refuses access if 10 Digit key is not provided
    return Scaffold(
        body: Center(
            child: Text('You do not have access to the map, please login')));
  }
}

你和我做的差不多;我的做法如下:

  1. 在您的状态 class 顶部将 BitmapDescriptor 设置为可为 null 的 属性,同时我创建一个 标记 集:
Set<Marker>? _markers = <Marker>{};
BitmapDescriptor? myMarker

我在 build 方法的开头创建了一个 async 方法 运行 (我在build 方法,因为我有时需要构建上下文),异步加载位图,如:

void setMarkerIcon() async {
  myMarker = await BitmapDescriptor.fromAssetImage(
        const ImageConfiguration(size: Size(50, 50)),'loginlogo.png');
}

然后在 build 方法中我只是调用它:

@override
  Widget build(BuildContext context) {
    
    // you can call it here
    setMarkerIcons();

    return Scaffold(
      body: GoogleMap(
        markers: _markers!,
        onMapCreated: (GoogleMapController ctrl) {
          
          // here after map is loaded, I generate the markers
          generateMarkers();
        }
      )
    );

奖金:

然后如上所示,在创建地图后,我可以继续使用基于位置列表的自定义标记,如下所示:

void generateMarkers() {
    var localMarkers = <Marker>{};

    for(var location in locationsList!) {
      localMarkers.add(
        Marker(
          markerId: MarkerId(location.id!),
          position: LatLng(location.lat!, location.lng!),
          icon: myMarker
        )
      );
    }

    if (mounted) {
        setState(() {
          _markers = localMarkers;
        });
      }
  }