I'm using google_maps_flutter: ^0.5.13 to develop a basic 'multiple markers on a google map' type Flutter screen.
I am curious how others set the initialCameraPostion for the GoogleMap() class. I either
Set it static initially
In the getMapMarkers() function, I will call a setMarkers(List<dynamic> markers) (that takes in a list of the markers or objects) and grab one of the GeoPoint from the list of markers and use that to set the initialCameraPosition.
class MapScreenState extends State<MapScreen> {
GoogleMapController _mapController;
// Method #1
static CameraPosition _initialCameraPosition =
CameraPosition(target: const LatLng(26.357540, -81.785290), zoom: 12);
void _onMapCreated(GoogleMapController controller) {
_mapController = controller;
_getMapMarkers();
}
#override
Widget build(BuildContext context) {
return Stack(children: <Widget>[_googleMap(context)]);
}
Widget _googleMap(BuildContext context) {
return Column(children: <Widget>[
Expanded(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
initialCameraPosition: _initialCameraPosition,
onMapCreated: _onMapCreated,
mapType: MapType.normal,
markers: Set<Marker>.of(markers.values),
),
),
)
]);
}
}
// Method #2
void _setCenter(List<dynamic> markers) {
GeoPoint geo = markers[0].geocode;
setState(() {
_initialCameraPosition =
CameraPosition(target: LatLng(geo.latitude, geo.longitude), zoom: 12);
});
}
initialCameraPosition only for the initial time. You can move the camera using the following way. We already got a camera controller using onMapCreated hook.
void _onMapCreated(GoogleMapController controller) {
_mapController = controller;
_getMapMarkers();
}
Using This _mapController we can access moveCamera function and move the camera to marker position.
_mapController.moveCamera(CameraUpdate.newLatLng(<LatLng one of your marker position>));
Example:
_mapController.moveCamera(CameraUpdate.newLatLng(LatLng(markerLat,markerLng)));
Related
I have tried to build a code from the internet which should draw two markers in goole maps. The difficulty is that the coordinates come from a cloud firestore. I don't know why, but I can`t see the markers. I did it the same way the people in the tutorial told me.
This is a screenshot of my firestore:
And this is the code I tried:
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class maps2 extends StatefulWidget {
#override
_maps2State createState() => _maps2State();
}
class _maps2State extends State<maps2> {
GoogleMapController controller;
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
void initMarker(specify, specifyId) async {
var markerIdVal = specifyId;
final MarkerId markerId = MarkerId(markerIdVal);
final Marker marker = Marker(
markerId: markerId,
position:
LatLng(specify['location'].latitude, specify['location'].longitude),
infoWindow: InfoWindow(title: 'Shop', snippet: specify['name']),
);
setState(() {
markers[markerId] = marker;
});
}
getMarkerData() async {
Firestore.instance.collection('data').getDocuments().then((myMockDoc) {
if (myMockDoc.documents.isNotEmpty) {
for (int i = 0; i < myMockDoc.documents.length; i++) {
initMarker(
myMockDoc.documents[i].data, myMockDoc.documents[i].documentID);
}
}
});
}
#override
void initState() {
getMarkerData();
super.initState();
}
#override
Widget build(BuildContext context) {
Set<Marker> getMarker() {
return <Marker>[
Marker(
markerId: MarkerId('Shop'),
position: LatLng(21.1458, 79.0882),
icon: BitmapDescriptor.defaultMarker,
infoWindow: InfoWindow(title: 'Home'))
].toSet();
}
return Scaffold(
body: GoogleMap(
markers: Set<Marker>.of(markers.values),
mapType: MapType.normal,
initialCameraPosition:
CameraPosition(target: LatLng(21.1458, 79.0882), zoom: 12.0),
onMapCreated: (GoogleMapController controller) {
controller = controller;
},
),
);
}
}
You need to change the code to:
initMarker(
myMockDoc.documents[i].data(), myMockDoc.documents[i].documentID);
}
I want to track user location. For this reason, I am using location package of flutter. Likewise, I am using Streams to track in real-time. but how can I show user location on the Google Maps in real time. I have some problem about showing real-time location on Google Maps.
** Here is my Location Service class **
class LocationService {
UserLocation _currentLocationofUser;
Location location = Location();
//Sürekli güncelle
StreamController<UserLocation> _locationController =
StreamController<UserLocation>.broadcast();
LocationService() {
location.requestPermission().then((granted) {
if (granted != null) {
location.onLocationChanged.listen((locationData) {
if (locationData != null) {
_locationController.add(UserLocation(
latitude: locationData.latitude,
longitude: locationData.longitude));
}
});
}
});
}
Stream<UserLocation> get locationStream => _locationController.stream;
** Here is my main class to show real-time location of user **
#override
_HomeViewState createState() => _HomeViewState();
}
class _HomeViewState extends State<HomeView> {
GoogleMapController _mapController;
#override
void initState() {
super.initState();
}
#override
Widget build(BuildContext context) {
var userLocation = Provider.of<UserLocation>(context);
return GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
zoom: 12,
target: LatLng(userLocation.latitude, userLocation.longitude)),
onMapCreated: (GoogleMapController controller) {
_mapController = controller;
},
);
}
}
GoogleMaps markers are not displaying after I query Firebase where location coordinates are stored as geopoints (latitude and longitude) under the collection 'markers.'
I have followed the changelog on the Flutter GoogleMaps plugin where markers where made as their own widget, without any success. I connect to the database using Firebase.instance and query through 'markers.' The for loops attempts to return the relevant information. populateClients and initMarkers are the the methods that are created to add the markers to the map, using the process described in the GoogleMaps recent marker update.
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geolocator/geolocator.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
class FirstScreen extends StatefulWidget {
const FirstScreen({Key key}) : super(key: key);
#override
State<FirstScreen> createState() => _FirstScreen();
}
class _FirstScreen extends State<FirstScreen> {
GoogleMapController mapController;
var currentLocation;
var clients = [];
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
#override
void initState(){
super.initState();
populateClients();
Geolocator().getCurrentPosition().then((currloc){
setState(() {
currentLocation = currloc;
});
});
}
populateClients() {
Firestore.instance.collection('markers').getDocuments().then((docs)
{
if(docs.documents.isNotEmpty) {
for(int i = 0; i < docs.documents.length; i++) {
//clients.add(docs.documents[i].data);
initMarker(docs.documents[i].data,
docs.documents[i].documentID);
}
}
});
}
void initMarker(client, markerRef) {
var markerIDVal = markerRef;
final MarkerId markerId = MarkerId(markerIDVal);
//new marker
final Marker marker = Marker(
position: LatLng(client['location'].latitude,
client['location'].longitude),
markerId: markerId,
);
setState(() {
// adding a new marker to map
markers[markerId] = marker;
});
}
#override
Widget build(BuildContext context) {
return currentLocation == null ? Container(
alignment: Alignment.center,
child: Center(
child: CircularProgressIndicator(),
),
):
Stack(
children: <Widget>[
GoogleMap(
initialCameraPosition:
CameraPosition(target: LatLng(currentLocation.latitude,
currentLocation.longitude), zoom: 17),
onMapCreated: _onMapCreated,
myLocationEnabled: true,
mapType: MapType.normal,
markers: Set<Marker>.of(markers.values),
),
],
);
}
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
});
}
}
The markers would display on the geolocation points that are stored in Firebase.
I am using flutter 1.3** version it's not defined markers syntax in GoogleMap()
GoogleMap(
onMapCreated: _onMapCreated,
markers: markers,
)
So i m using below code to try to get lat and long from map
void _onMapCreated(GoogleMapController controller){
this._controller = controller;
controller.onMarkerTapped.add(_onMarkerTapped);
}
void _onMarkerTapped(Marker marker) {
...
}
Widget build(BuildContext context) {
GoogleMap(
onMapCreated: _onMapCreated,
options: GoogleMapOptions(
...
));
}
My question is how to get lat and long using MarkerOptions and above methods into string values?
LocationData currentLocation;
getLocation() async {
var location = new Location();
location.onLocationChanged().listen(( currentLocation) {
print(currentLocation.latitude);
print(currentLocation.longitude);
setState(() {
latLng = LatLng(currentLocation.latitude, currentLocation.longitude);
});
print("getLocation:$latLng");
loading = false;
});
}
From this above code, you simply get a Lattitude and longitude
and use this latLng variable on
initialCameraPosition: CameraPosition(
target: latLng,
zoom: 17.4746,
),
this method in GoogleMap
This Code Maybe Helpful to you.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Google Maps Demo',
home: MapSample(),
);
}
}
class MapSample extends StatefulWidget {
#override
State<MapSample> createState() => MapSampleState();
}
class MapSampleState extends State<MapSample> {
Completer<GoogleMapController> _controller = Completer();
static final CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);
static final CameraPosition _kLake = CameraPosition(
bearing: 192.8334901395799,
target: LatLng(37.43296265331129, -122.08832357078792),
tilt: 59.440717697143555,
zoom: 19.151926040649414);
#override
Widget build(BuildContext context) {
return new Scaffold(
body: GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
floatingActionButton: FloatingActionButton.extended(
onPressed: _goToTheLake,
label: Text('To the lake!'),
icon: Icon(Icons.directions_boat),
),
);
}
Future<void> _goToTheLake() async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(_kLake));
}
}
I am using Google Maps for Flutter widget.
In my app map is displayed via one of the tabs of BottomNavigationBar.
And I have the following problem:
user is on Map's tab
user changes tab (by tapping on another one)
[PROBLEM] when user returns on Map's tab map redraws.
I would like to keep map as it is when user leaves Map's tab, so he can continue to work with it when he returns to it later on.
Tried to:
use PageStorage - without success.
make something like Singletone of Map's state - without success.
use AutomaticKeepAliveClientMixin (saw here), which looked promising, but still without success.
(I admit that I could have done something wrong)
Code of last attempt:
class MapScreen extends StatefulWidget {
#override
State<StatefulWidget> createState() => MapScreenState();
}
class MapScreenState extends State<MapScreen> with AutomaticKeepAliveClientMixin {
GoogleMapController mapController;
#override
bool get wantKeepAlive => true;
#override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
appBar: AppBar(
title: const Text("Map"),
),
body: GoogleMap(
onMapCreated: _onMapCreated,
)
);
}
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
updateKeepAlive();
}
}
So, I just need a way to either keep MapScreen alive and unchanged, or to store its state somehow and restore it when user returns to MapScreen. Or something else which will solve the problem.
Use IndexedStack
For example:
Class _ExamplePageState extends State<ExamplePage> {
int _bottomNavIndex = 0;
final List<Widget> _children = [
WidgetOne(),
WidgetTwo(),
GoogleMap(),
]
#override
Widget build(BuildContext context) {
return Scaffold(
body: IndexedStack(
index: _bottomNavIndex,
children: _children,
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _bottomNavIndex,
onTap: (index) {
if (_bottomNavIndex == index) return;
setState(() {
_bottomNavIndex = index;
});
}
items: [ ... ]
),
);
}
}
Widget always rebuild after you change from page to page, so, try this , use a variable for GoogleMap and reuse if it's different from null.
GoogleMap _map;
#override
Widget build(BuildContext context) {
if (_map == null){
_map = GoogleMap(
onMapCreated: _onMapCreated,
);
}
return Scaffold(
appBar: AppBar(
title: const Text("Map"),
),
body:_map,
);
}
I was just having this same problem and the mixin solved it. I think you've just missed enter the type of mixin at the end of its declaration.
class MapScreenState extends State<MapScreen> with AutomaticKeepAliveClientMixin<MapScreenState>
see this thread if anything.
AutomaticKeepAliveClientMixin
To
AutomaticKeepAliveClientMixin<MapScreenState>