Flutter cannot refresh GoogleMap after getting coordinates - flutter

I have an app that implements GoogleMap.
I can go back to the page and get a nice map with premade settings, but I cannot make the map refresh when i press the button and nothing is set beforehand .
The widget is created on Build() and I have a button that gets the lat and lng from geolocator and also cityname reverse lookup.
That calls
SaveGPS() when it is done with everything.
I normally go directly from the Prefs.lat Prefs.lng, but I tried creating member variables _lng and _lat including a _zoom variable so that setState will work.. it does not work. Not sure what I'm doing wrong.
Container(
width: 350,
height: 350,
child: GoogleMap(
markers: Set<Marker>.of(_markers),
mapType: MapType.satellite,
initialCameraPosition:
CameraPosition(zoom: _zoom, target: LatLng(_lat, _lng))),
),
void saveGps() async {
DateTime now = DateTime.now();
var timezoneOffset = now.timeZoneOffset;
Prefs.cityName = _cityName;
Prefs.offset = timezoneOffset.inMinutes / 60;
setState(() {
_lat = Prefs.lat = _position.latitude;
_lng = Prefs.lng = _position.longitude;
_markers.clear();
_markers.add(Marker(
markerId: MarkerId(Prefs.cityName),
position: LatLng(Prefs.lat, Prefs.lng),
infoWindow: InfoWindow(
title: Prefs.cityName,
)));
_zoom = 17;
});
}

I used a map controller and did an animateCamera call. This was the only way to make it work. Other items update with setState but not this one.
// create this in your class
Completer<GoogleMapController> _controller = Completer();
// build method here..
Container(
width: 350,
height: 350,
child: GoogleMap(
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
markers: Set<Marker>.of(_markers),
mapType: MapType.satellite,
initialCameraPosition: CameraPosition(
zoom: 16, target: LatLng(Prefs.lat, Prefs.lng))),
),
When you want to save the new map or display it,
call this code here:
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(zoom: 17, target: LatLng(Prefs.lat, Prefs.lng))));

Related

FLUTTER - show all markers maps from list json API

anyone please help me for displaying markers maps from list json on flutter google maps.
i dont know this is right way or not for displaying markers from list json. my markers on map not showing
My services API
Future<List<UnitModel>> getUnit() async {
var url = 'myprivateurl';
var response = await http
.get(Uri.parse('$url/unit'), headers: {'api-key': 'privateapi'});
if (response.statusCode == 200) {
Map<String, dynamic> jsonData = json.decode(response.body);
List<dynamic> data = jsonData["data"];
setState(() {
listLatLngUnit = data;
return listLatLngUnit;
});
}
print(listLatLngUnit);
}
and my code
List<UnitModel> listLatLngUnit = [];
Container(
width: double.infinity,
height: 300,
child: GoogleMap(
onMapCreated: (GoogleMapController controller){
_controller.complete(controller);
},
markers: listLatLngUnit.map((latLong) => Marker(markerId: MarkerId(latLong.unitLat.toString()),
position: LatLng((latLong.unitLat),
(latLong.unitLong)))).toSet(),
initialCameraPosition: CameraPosition(
target: const LatLng(-6.009756, 106.046373),
// target: _center,
// target: const LatLng(0,0),
zoom: 11.0,
),
),
),

How to pass a googleMapController to custom widget? (Flutter)

On my flutter googleMap i have quickDialButton, which has multiple buttons. One of them is supposed to center the camera of the parent mapWidget which happens via the googleMapControllet that i am passing as a parameter.
return Scaffold(
body: GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(42, 23), zoom: 11.5),
myLocationButtonEnabled: false,
zoomControlsEnabled: false,
mapToolbarEnabled: false,
onMapCreated: (controller) {
googleMapController = controller;
},
markers: customMarkers.toSet(),
),
floatingActionButton: MyQuickDialButton(
c: googleMapController,
latitude: userLocation.latitude,
longitude: userLocation.longitude,
),
The problem is that the googleMapController gets initialized after the floatingActionButton property to the scaffold. How can i update it after i have the controller initialized.
Instead of passing this controller, i created new function that can run controller methods from the parent widget.
void _centerCamera() {
googleMapController.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(userLocation.latitude, userLocation.longitude),
zoom: 16)));
}
...
floatingActionButton: MyQuickDialButton(
c: _centerCamera,
latitude: userLocation.latitude,
longitude: userLocation.longitude,
)
and later i am calling just the function "c" from the child widget

Flutter google maps: Change selected marker icon dynamically

I am using google map package on my flutter project. I have a page in which google map is shown in a full screen and carousel of products (horizontally scrollable) over it. Clicking each marker will slide carousel to reveal the product info widget.
I have following codes
CameraPosition _productLocation;
Set<Marker> markers = Set();
int _currentIndex = 0;
BitmapDescriptor defaultIcon =
BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed); //default marker
BitmapDescriptor selectedIcon =
BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueViolet); //selected marker
#override
void initState() {
super.initState();
_productLocation = CameraPosition(
target: LatLng(0, 0),
zoom: 16,
);
if (widget.productList.length > 0) {
widget.productList.asMap().forEach((index, v) {
Marker resultMarker = Marker(
icon: _currentIndex == index ? selectedIcon : defaultIcon,
consumeTapEvents: true,
markerId: MarkerId(v.slug),
position:
LatLng(double.parse(v.latitude), double.parse(v.longitude)),
onTap: () {
setState(() {
_currentIndex = index;
});
buttonCarouselController.animateToPage(index);
});
// Add it to Set
markers.add(resultMarker);
});
}
}
#override
Widget build(BuildContext context) {
size = Screen(MediaQuery.of(context).size);
return Scaffold(
backgroundColor: Colors.white,
extendBodyBehindAppBar: true,
body: Container(
width: double.infinity,
height: double.infinity,
child: GoogleMap(
markers: markers,
mapType: MapType.normal,
initialCameraPosition: _productLocation,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
),
);
Problem
The first time when we enter the page, i.e. if _currentIndex==0, the first marker is blue in color and first product info widget is shown, rest are red color. Something that doesn't work is when I click another marker, I want this marker to turn blue and rest all red. So in short, I want selected marker to be blue. Can anybody please throw some light on it?
Thanks
Your issue is that your markers set their color in initState() which only happens once for the Widget. (so the setState() fires, but the markers Set is unchanged)
You need to move the Set<Marker> markers population either into build() or refactor it so that it get's re-populated from the marker onTap()

Flutter : Google Maps - updating maps bearing automatically using value from stream builder

I have a compass plugin that is giving direction angle, and also location plugin that provide the current location. With these plugins, I use google maps placed under Streambuilder to put my current location as marker and with a line to another location.
The issue I am facing currently is how to rotate the map automatically when the device is rotated, as the first plugin provides direction angle (double value) that gets updated streams as the device rotate.
I wanted to use this angle value to update Google Maps bearing automatically, so that the map rotates accordingly.
I have tired many ways but of no use. Google maps does not respond.
this is my code:
Completer<GoogleMapController> _controller = Completer();
return StreamBuilder(
stream: FlutterQiblah.qiblahStream,
builder: (_, AsyncSnapshot<QiblahDirection> snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) return LoadingIndicator();
final qiblahDirection = snapshot.data;
_goToTheLake(qiblahDirection);
return GoogleMap(
mapType: MapType.satellite,
zoomGesturesEnabled: true,
compassEnabled: true,
myLocationEnabled: false,
myLocationButtonEnabled: true,
rotateGesturesEnabled: true,
initialCameraPosition: CameraPosition(
target: position,
zoom: 18,
// bearing: qiblahDirection.direction,
),
markers: Set<Marker>.of(
<Marker>[
widget.meccaMarker,
Marker(
draggable: true,
markerId: MarkerId('Marker'),
position: position,
icon: BitmapDescriptor.defaultMarker,
rotation: qiblahDirection.qiblah,
onTap: () {
_goToTheLake(qiblahDirection);
},
onDragEnd: (LatLng value) {
position = value;
_positionStream.sink.add(value);
},
zIndex: 5,
),
],
),
circles: Set<Circle>.of([
Circle(
circleId: CircleId("Circle"),
radius: 10,
center: position,
fillColor: Theme.of(context).primaryColorLight.withAlpha(100),
strokeWidth: 1,
strokeColor: Theme.of(context).primaryColorDark.withAlpha(100),
zIndex: 3,
)
]),
polylines: Set<Polyline>.of([
Polyline(
polylineId: PolylineId("Line"),
points: [position, QiblahMaps.LatLong],
color: Theme.of(context).primaryColor,
width: 5,
zIndex: 4,
)
]),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
);
},
)
I have placed this function as future called from inside stream builder in order to change the "bearing" of the map:
final GoogleMapController controller = await _controller.future;
controller.moveCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
bearing: qiblahDirection.direction,
),
),
);
} ```
Try this plugin flutter_compass
use the events to update google map bearing as you wish

Add custom marker to map in flutter with mapbox plugin

to provide a better ui to my app I need to display a small card with the user name and a small circle with the user picture or avatar.
Is there any way to do it with the flutter-mapbox-gl plugin?
The best solutions for that is inside mapbox-gl package example folder :
https://github.com/tobrun/flutter-mapbox-gl/blob/master/example/lib/place_symbol.dart
here small example what you can do
Widget build(BuildContext context) {
mapController.addSymbol(
SymbolOptions(
geometry: LatLng(-33.86711, 151.1947171),
iconImage: "assets/images/ur_image.png",
),
);
return Scaffold(
body: Center(
child: SizedBox(
width: double.infinity,
height: 300.0,
child: MapboxMap(
styleString: themeControl.themeSet.mapStyle,
onMapCreated: _onMapCreated,
onStyleLoadedCallback: _onStyleLoaded,
zoomGesturesEnabled: _zoomGesturesEnabled,
myLocationEnabled: _myLocationEnabled,
initialCameraPosition: const CameraPosition(
target: LatLng(-33.852, 151.211),
zoom: 11.0,
),
),
),
),
);}
After fighting with this for 2h that's what I came up with:
Add to widget tree:
Center(
child: SizedBox(
width: double.infinity,
height: 300,
child: MapboxMap(
initialCameraPosition: CameraPosition(
target: latLng,
zoom: 13,
),
onMapCreated: onMapCreated,
accessToken: mapboxPublicToken,
),
),
)
Some remarks:
latLng is e.g. LatLng(-33.852, 151.211)
the SizedBox was needed for my case to avoid Horizontal viewport was given unbounded height error
Then to add the actual marker (which in my case should be just in the center of the map, same as the target of CameraPosition):
Future<Uint8List> loadMarkerImage() async {
var byteData = await rootBundle.load("images/poi.png");
return byteData.buffer.asUint8List();
}
void onMapCreated(MapboxMapController controller) async {
var markerImage = await loadMarkerImage();
controller.addImage('marker', markerImage);
await controller.addSymbol(
SymbolOptions(
iconSize: 0.3,
iconImage: "marker",
geometry: latLng,
iconAnchor: "bottom",
),
);
}
A few remarks:
I had no luck with the "built in" markers. This should be the list of supported markers but I couldn't get them to work
images/poi.png in my case is just a 256x256 PNG image with transparent background
for rootBundle to work you need to import 'package:flutter/services.dart'
iconMarker tells how to position the marker. In my case it is kind of a pin icon 📍 so I want the "center bottom" to be where the lat/lng is.
iconSize you need to find out the best size. In my case I needed to hot restart every time I did a change which was annoying…
I expanded this answer into a blog post to cover also some problems I faced during installation.