skip to Main Content

I’m vague at such stuffs of Google Maps. While the markers are available on the map, the polyline doesn’t appear in the screen and I don’t seem to be able to place markers outside of Widget build.

class _MapScreenState extends State<MapScreen> {
  late GoogleMapController mapController;

  LatLng? currentLocation;
  double? currentlat;  double? currentlong;
  LatLng destination = const LatLng(4.66968, 101.07338);
  bool _isLoading = true;
  Set<Marker> markers = {};
  PolylinePoints polylinePoints = PolylinePoints();
  Map<PolylineId, Polyline> polylines = {};
  List<LatLng> polylineCoordinates = [];

  @override
  void initState() {
    super.initState();
    getLocation();
    makeLines();
    addPolyLine();
  }

  getLocation() async {
    Position position = await Geolocator.getCurrentPosition(
        desiredAccuracy: LocationAccuracy.high);
    double lat = position.latitude;
    double long = position.longitude;

    LatLng location = LatLng(lat, long);
    currentlat = lat;
    currentlong = long;

    setState(() {
      currentLocation = location;
      _isLoading = false;
    });
    print("Current Lat: $lat, Long: $long");
  }

  addPolyLine() {
    PolylineId id = const PolylineId("poly");
    Polyline polyline = Polyline(
      polylineId: id,
      color: Colors.blue,
      points: polylineCoordinates,
      width: 3,
    );
    polylines[id] = polyline;
  }

  void makeLines() async {
    await polylinePoints
        .getRouteBetweenCoordinates(
      'API KEY',
      PointLatLng(currentlat??0, currentlong??0),
      PointLatLng(destination.latitude, destination.longitude), //End LATLANG
      travelMode: TravelMode.transit,
    )
        .then((value) {
      value.points.forEach((PointLatLng point) {
        polylineCoordinates.add(LatLng(point.latitude, point.longitude));
      });
    }).then((value) {
      addPolyLine();
    });
  }

  void _onMapCreated(GoogleMapController controller) {
    mapController = controller;
  }
  

  @override
  Widget build(BuildContext context) {
    Marker destinationMarker = Marker(
      markerId: const MarkerId('targetLocation'),
      position: destination,
      infoWindow: const InfoWindow(title: 'Destination'),
    );

      
    Marker currentLocationMarker = Marker(
      icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue),
      markerId: const MarkerId('currentLocation'),
      position: LatLng(currentlat??0, currentlong??0),
      infoWindow: const InfoWindow(title: 'Current Location'),
    );

    return Scaffold(
      appBar: AppBar(
        title: const Text('Map'),
      ),
      body: _isLoading
          ? const Center(child: CircularProgressIndicator())
          : Center(
            child: Column(
              children: [
                Expanded(
                  child: GoogleMap(
              myLocationEnabled: true,
              onMapCreated: _onMapCreated,
              markers: <Marker>{destinationMarker, currentLocationMarker},
              polylines: Set<Polyline>.of(polylines.values),
              initialCameraPosition: CameraPosition(
                target: currentLocation!,
                zoom: 16.0,
              ),
            ),
                )
              ],
            ),
          )
    );
  }
}

Current Output : https://phpout.com/wp-content/uploads/2023/06/YYaJb-jpg.webp

The name of locations are hidden due to containing my current location.

How do I place the markers outside of widget build and then make the polyline between markers available?

2

Answers


  1. Go check Flutter Campus, there’s something you want.

    Login or Signup to reply.
  2. The issue was happening cause the map renders on the screen but the polyLines are still not generated.

    You need to use cubit, that manage all those async gaps for get current location and finding polyLines.

    you can refer to the the below code:

    MapsCubit.dart:

    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:flutter_polyline_points/flutter_polyline_points.dart';
    import 'package:geolocator/geolocator.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    
    part 'maps_state.dart';
    
    class MapsCubit extends Cubit<MapsState> {
      MapsCubit() : super(MapsInitial());
    
      Future<void> getCurrentLocation() async {
        emit(MapsLoadingState());
    
        try {
          Position position = await Geolocator.getCurrentPosition(
              desiredAccuracy: LocationAccuracy.high);
          double lat = position.latitude;
          double long = position.longitude;
    
          LatLng location = LatLng(lat, long);
    
          emit(ObtainedCurrentLocation(location: location));
        } catch (e) {
          emit(MapsErrorState(
              errorMessage: 'Error while fetching the current location.'));
        }
      }
    
      Future<void> getPolyLines(LatLng currentLocation, LatLng destination) async {
        emit(MapsLoadingState());
        try {
          List<LatLng> latLngList = [];
    
          PolylinePoints points = PolylinePoints();
    
          PolylineResult polylineResult = await points.getRouteBetweenCoordinates(
            'API KEY',
            PointLatLng(currentLocation.latitude, currentLocation.latitude ?? 0),
            PointLatLng(destination.latitude, destination.longitude),
            travelMode: TravelMode.transit,
          );
    
          polylineResult.points.forEach((ele) {
            latLngList.add(LatLng(ele.latitude, ele.longitude));
          });
    
          List<Polyline> polyLines = [];
          polyLines.add(Polyline(
              polylineId: const PolylineId('PolylineId'), points: latLngList));
    
          emit(ObtainedPolyLines(polyLines: polyLines));
        } catch (e) {
          emit(MapsErrorState(errorMessage: 'Error while finding route'));
        }
      }
    }
    

    MapsSate.dart:

    part of 'maps_issue_cubit.dart';
    
    abstract class MapsState {}
    
    class MapsInitial extends MapsState {}
    
    class MapsLoadingState extends MapsState {}
    
    class ObtainedCurrentLocation extends MapsState{
      LatLng location;
    
      ObtainedCurrentLocation({required this.location});
    }
    
    class ObtainedPolyLines extends MapsState {
      List<Polyline> polyLines;
    
      ObtainedPolyLines({required this.polyLines});
    }
    
    class MapsErrorState extends MapsState {
      String errorMessage;
    
      MapsErrorState({required this.errorMessage});
    }
    

    And Maps.dart:

    import 'package:flutter/material.dart';
    import 'package:flutter_bloc/flutter_bloc.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    import 'package:mobile_delivery_v2/maps_issue/maps_issue_cubit.dart';
    
    class Maps extends StatefulWidget {
      const Maps({super.key});
    
      @override
      State<Maps> createState() => _MapsState();
    }
    
    class _MapsState extends State<Maps> {
      late MapsCubit cubit;
    
      late GoogleMapController mapController;
      late LatLng destination;
      late LatLng currentLocation;
      Set<Marker> markers = {};
    
      @override
      void initState() {
        super.initState();
        destination = const LatLng(4.66968, 101.07338);
        currentLocation = const LatLng(0, 0);
        cubit = MapsCubit();
        cubit.getCurrentLocation();
      }
    
      void _onMapCreated(GoogleMapController controller) {
        mapController = controller;
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
            appBar: AppBar(
              title: const Text('Map'),
            ),
            body: BlocConsumer(
              bloc: cubit,
              listener: (context, state) {
                if (state is ObtainedCurrentLocation) {
                  currentLocation = state.location;
                  cubit.getPolyLines(
                      currentLocation, destination);
                  markers.addAll([
                    Marker(
                      markerId: const MarkerId('1'),
                      position: currentLocation,
                    ),
                    Marker(markerId: const MarkerId('2'), position: destination)
                  ]);
                }
              },
              builder: (context, state) {
                if (state is ObtainedPolyLines) {
                  return GoogleMap(
                    myLocationEnabled: true,
                    onMapCreated: _onMapCreated,
                    markers: markers,
                    polylines: Set<Polyline>.of(state.polyLines),
                    initialCameraPosition: CameraPosition(
                      target: currentLocation,
                      zoom: 16.0,
                    ),
                  );
                } else if (state is MapsLoadingState) {
                  return const Center(
                    child: CircularProgressIndicator(),
                  );
                } else if (state is MapsErrorState) {
                  return Center(
                    child: Text(state.errorMessage),
                  );
                }
                return const SizedBox.shrink();
              },
            ));
      }
    }
    

    Now the cubit methods getCurrentLocation and getPolyLines will manage the async operation of the getting current location and generating polyLines respectively and will emit a state, and bloc consumer will catch it and will show google maps.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search