There are many times when you are making an application and you may need to use Maps as well as Location to work around. What can be the better map than the Google Maps itself?
Before we start, it is better to clear what we will be needing:
- Permission Handler
For allowing the application to access user\’s location. - Google Maps
Well, that is the topic. - Location
Why map without your location?
The followings can be installed by keeping the package name along with the version in the pubspec.yaml
file, found in the root.
Starting off, the permission can be asked at any given time but the package must be imported first. It can be at the very beginning of the application or when you are actually trying to access the map. For this tutorial, I placed a button in the home that will specifically ask for.
import \'package:google_maps_flutter/google_maps_flutter.dart\';
Before the permission is asked, the permission tag for location has to be added in the AndroidManifest.xml
file. The file can be found at: app\\src\\main\\AndroidManifest.xml
Add the following statement right after the opening tag of manifest
.
<uses-permission android:name=\"android.permission.ACCESS_FINE_LOCATION\" />
As well as the Google API Key (you can get it from here) in the application
tag before activity
tag. Like this:
<meta-data android:name=\"com.google.android.geo.API_KEY\" android:value=\"YOUR-API-KEY\"/>
Then the following function should be called.
Future doLocationPermissionAsk() async {
Map<PermissionGroup, PermissionStatus> permissions = await PermissionHandler().requestPermissions([PermissionGroup.location]);
}
The above function is called by the following button. If permission has been granted already, nothing happens. Otherwise it will bring the popup question.
RaisedButton( child: Text(\'Ask for permission\'), onPressed: () { doLocationPermissionAsk(); }, ),
For keeping things fairly simply, I created another screen for the map. The first import is the Google Map
itself along with the Location
package. Dart Async
is used since a lot of calls will keep happening meanwhile the foreground looks smooth.
import \'dart:async\';
import \'package:google_maps_flutter/google_maps_flutter.dart\';
import \'package:location/location.dart\';
The following objects are instantiated:
//A controller for GoogleMaps widget
Completer<GoogleMapController> _controller = Completer();
Location location = Location();
//The marker for user\'s selected location
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
CameraPosition cameraPosition;
//The initial camera position.
static final CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);
//For updating the location when the camera position is changed.
void updateMarker(CameraPosition position){
final MarkerId markerId = MarkerId(\"selectedLocation\");
Marker marker = Marker(
markerId: markerId,
position: LatLng(position.target.latitude, position.target.longitude),
onTap: (){
print(\"Location selected\");
}
);
//The marker needed to be displayed on the map
markers[markerId] = marker;
The build
method will be a normal one with a Scaffold
inside.
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text(\'The Google Maps Tutorial\'),
),
body: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
myLocationEnabled: true,
markers: Set<Marker>.of(markers.values),
onCameraMove: (position){
setState(() {
cameraPosition = position;
});
updateMarker(cameraPosition);
},
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
floatingActionButton: FloatingActionButton.extended(
onPressed: (){
Navigator.pop(context, cameraPosition);
},
label: Text(\'Location confirmed!\')
),
);
}
In the above code, GoogleMaps
is a widget has the following properties and events (along with why).
mapType
be a hybrid, satellite or normal with no satellite images.initialCameraPosition
where the map should start showing from.myLocationEnabled
the icon for showing your location should be shown or not.markers
those red pins shown on the map for some user selected location. We will be using this for showing the user selected location.onCameraMove
will occur when the camera is (view) is changed and continues to be called until the camera movement stops.onMapCreated
will occur right after the map is loaded completely and it will update our_controller
that the map is completely loaded.
Then we have a button for confirming the location the user has selected. This can be done in the marker
by using the onTap
event. That might also make the user
confuse. That floating action button (FAB) is popping the current screen and passing back the selected coordinates back to the main
page.
The file would look like this.
import \'dart:async\';
import \'package:flutter/material.dart\';
import \'package:google_maps_flutter/google_maps_flutter.dart\';
import \'package:location/location.dart\';
class MapScreen extends StatefulWidget {
@override
_MapScreenState createState() => _MapScreenState();
}
class _MapScreenState extends State<MapScreen> {
Completer<GoogleMapController> _controller = Completer();
Location location = Location();
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
CameraPosition cameraPosition;
static final CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);
void updateMarker(CameraPosition position){
final MarkerId markerId = MarkerId(\"selectedLocation\");
Marker marker = Marker(
markerId: markerId,
position: LatLng(position.target.latitude, position.target.longitude),
onTap: (){
print(\"Location selected\");
}
);
markers[markerId] = marker;
}
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: AppBar(
title: Text(\'The Google Maps Tutorial\'),
),
body: GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _kGooglePlex,
myLocationEnabled: true,
onCameraMove: (position){
//debugPrint(\"Camera Position Ghulam Mustafa $position \");
setState(() {
cameraPosition = position;
});
updateMarker(cameraPosition);
},
markers: Set<Marker>.of(markers.values),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
floatingActionButton: FloatingActionButton.extended(
onPressed: (){
Navigator.pop(context, cameraPosition);
},
label: Text(\'Location confirmed!\'),
),
);
}
}
While on the main
screen, you can call the mapScreen
like this for getting the coordinates.
CameraPosition cameraPosition = await Navigator.of(context).push(MaterialPageRoute(builder: (context) => MapScreen()));
The code for the following can be found in GitHub.
A word of advice: If you are trying to add permissions, location, or those advanced level things, always uninstall the entire application from your phone from one phase to another.
For example, if you run the application without Maps or Location and then add Location later. This location may not work until you uninstall and install the application again.
Do not pull out your hair because of that.
Leave a Reply