I'm using : google_maps_flutter: ^2.1.6
flutter version : 3.0.1
dart version : 2.17.1
I can through the controller add marker, polygon, polyline and circles, but I couldn't change this icon that represents my location.
import 'dart:io';
import 'package:exemplo/controller/google_maps_controller.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class GoogleMapsWidget extends StatefulWidget {
const GoogleMapsWidget({super.key});
#override
State<GoogleMapsWidget> createState() => _GoogleMapsWidgetState();
}
class _GoogleMapsWidgetState extends State<GoogleMapsWidget> {
final GoogleMapsController googleMapsController = GoogleMapsController();
#override
void initState() {
googleMapsController.gpsPermission();
if (Platform.isAndroid) {
AndroidGoogleMapsFlutter.useAndroidViewSurface = true;
}
super.initState();
}
#override
void dispose() {
googleMapsController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: googleMapsController,
builder: (BuildContext context, Widget? child) => GoogleMap(
markers: googleMapsController.marker,
polygons: googleMapsController.polygon,
mapType: MapType.normal,
zoomControlsEnabled: true,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target: LatLng(
googleMapsController.lat,
googleMapsController.long,
),
zoom: 15,
),
onMapCreated: googleMapsController.onMapCreated,
onTap: googleMapsController.selectLocal,
),
);
}
}
That blue ball in the middle
Related
Here's the code that I have so far
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class TempView extends StatefulWidget {
const TempView({Key? key}) : super(key: key);
#override
State<TempView> createState() => _TempViewState();
}
class _TempViewState extends State<TempView> {
final Completer<GoogleMapController> _controller =
Completer<GoogleMapController>();
static const CameraPosition _kGooglePlex = CameraPosition(
target: LatLng(37.42796133580664, -122.085749655962),
zoom: 14.4746,
);
static const CameraPosition _kLake = CameraPosition(
bearing: 192.8334901395799,
target: LatLng(37.43296265331129, -122.08832357078792),
tilt: 59.440717697143555,
zoom: 19.151926040649414);
#override
Widget build(BuildContext context) {
return Scaffold(
body: GoogleMap(
onTap: (argument) => print("tapped"),
mapType: MapType.hybrid,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
),
floatingActionButton: FloatingActionButton.extended(
onPressed: _goToTheLake,
label: const Text('To the lake!'),
icon: const Icon(Icons.directions_boat),
),
);
}
Future<void> _goToTheLake() async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(_kLake));
}
}
It's the same as the code on the pub.dev page for the google_maps_flutter widget, except I added an onTap.
For some reason the onTap never fires! I've even tried adding custom gesture recognisers into the gestureRecognizers set, like the EagerGestureRecognizer and the TapGestureRecognizer.
I'm on Flutter 3.7 macOS with Apple M1.
Why isn't it working, and how can I get around this?
Wrap GoogleMap widget with InkWell Widget and use its property of onTap, it will work.
InkWell(
onTap: () => ,
child:
),
I ran your code and it seems to run just fine. tapped gets printed every time i tap on map.
Please make sure your tap is in GoogleMap region and that no other widget is overlaying if this isn’t the whole code.
I'm trying to have a page in my app display a user's location on a google map, which works in debug mode, but when I run it in release mode it simply loads indefinitely. The strange thing is that if I click on a different page on my app and go back to the map page it will immediately show. Does anyone know what could be going on here?
I also get the following error: [ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: MissingPluginException(No implementation found for method camera#animate on channel plugins.flutter.io/google_maps_0)
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:mapapp/provider/location_provider.dart';
import 'package:provider/provider.dart';
class Map extends StatefulWidget {
const Map({Key? key}) : super(key: key);
#override
_State createState() => _State();
}
class _State extends State<Map> {
#override
void initState() {
super.initState();
Provider.of<LocationProvider>(context, listen: false).initalization();
}
//Sets map style once app is resumed to reload the map
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state == AppLifecycleState.resumed) {
dynamic controller;
controller.setMapStyle("[]");
}
}
#override
Widget build(BuildContext context) {
return Scaffold(body: googleMapUI());
}
Widget googleMapUI() {
return Consumer<LocationProvider>(builder: (
consumerContext,
model,
child,
) {
while (model.locationPosition != null) {
return Column(
children: [
Expanded(
child: GoogleMap(
mapType: MapType.normal,
padding: const EdgeInsets.only(top: 40.0),
initialCameraPosition:
CameraPosition(target: model.locationPosition!, zoom: 18),
myLocationEnabled: true,
myLocationButtonEnabled: true,
onMapCreated: (GoogleMapController controller) async {
Provider.of<LocationProvider>(context, listen: false);
},
),
)
],
);
}
return const Center(
child: CircularProgressIndicator(),
);
});
}
}
i start with this code but all what i get white screen
how i can use google map to get current location or choose location.I am using GoogleMap package in flutter to get the required current location.
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 createState() => MapSampleState();
}
class MapSampleState extends State {
Completer _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 _goToTheLake() async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(_kLake));
}
}
If you're using Url properly(no spelling/parameter mistakes) with API key and there's no error from the server which happens a lot due to restrictions. Then there are other steps you need to, ask Location permission on app loading using https://pub.dev/packages/permission_handler package like this.
Code can be something like this.
Create an app_persmission_provider file.
class AppPermissionProvider with ChangeNotifier {
PermissionStatus _locationStatus = PermissionStatus.denied;
LatLng? _locationCenter;
final location_package.Location _location =
location_package.Location();
location_package.LocationData? _locationData;
// Getter
get locationStatus => _locationStatus;
get locationCenter => _locationCenter;
get location => _location;
void getLocationStatus() async {
final status = await Permission.location.request();
_locationStatus = status;
notifyListeners();
print(_locationStatus);
}
void getLocation() async {
_locationData = await _location.getLocation();
_locationCenter = LatLng(
_locationData!.latitude as double, _locationData!.longitude as double);
notifyListeners();
}
}
Then declare the provider on the root maybe, and In my case, I'm initializing some functions onInit. By doing so, android will ask for permission for location when your page loads.
#override
void initState() {
super.initState();
appPermission = Provider.of<AppPermissionProvider>(context, listen: false);
appPermission.getLocationStatus();
appPermission.getLocation();
}
And then using consumer.
SafeArea(
child: Consumer<AppPermissionProvider>(
builder: (context, appPermissionProvider, _) => appPermission
.locationCenter ==
null
? const Center(child: CircularProgressIndicator())
:
GoogleMap( myLocationButtonEnabled:
appPermissionProvider.locationStatus ==
PermissionStatus.granted
? true
: false,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target: appPermission.locationCenter,
zoom: 14,
),
onMapCreated: onMapCreated,
mapType: MapType.normal,
compassEnabled: true,
),
),
)
Here, I am checking if permission is granted, also I am only enabling myLocationButton if location permission is granted.
You can use google_maps_flutter package ,
A short example how you can use it.
For more clearity you can visit
Here or you can use geolocator.
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
LatLng _initialcameraposition = LatLng(20.5937, 78.9629);
GoogleMapController _controller;
Location _location = Location();
void _onMapCreated(GoogleMapController _cntlr)
{
_controller = _cntlr;
_location.onLocationChanged.listen((l) {
_controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(target: LatLng(l.latitude, l.longitude),zoom: 15),
),
);
});
}
I am newbie in flutter, I am trying to set my location as the center point of the map that the app draw on the screen
I am using statefulwidget as the root of my app and add this code :
class MyMap extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return MyMapState();
}
}
class MyMapState extends State<MyMap> {
GoogleMapController googleMapController;
LocationData currentLocation;
LocationData distinationLocation;
Location location;
#override
void initState() {
location = Location();
setInitSourceAndDestination();
super.initState();
}
setInitSourceAndDestination() async {
currentLocation = await location.getLocation();
}
#override
Widget build(BuildContext context) {
CameraPosition initialCameraPosition = CameraPosition(
target: LatLng(currentLocation.latitude, currentLocation.longitude),);
return GoogleMap(
initialCameraPosition: initialCameraPosition,
onMapCreated: (GoogleMapController controller) => googleMapController = controller,
mapType: MapType.normal,
tiltGesturesEnabled: false,
compassEnabled: true,
myLocationEnabled: true,
);
}
}
But there are a problem I can not solve:
the map is drawn in the screen before currentLocation is set
I tried setState and the problem has not been solved.
How can I make the app draw the map after setInitSourceAndDestination method finish excuting?
What make me confused is that the code at this form the build method will be excuted before setInitSourceAndDestination method finished, but if I add setState and change the currentLocation value inside it to rebuild the screen I noticed that setState executed before build function but it still dont show my location
Add a condition to check the state. If the state is null, then draw a loading indicator. If not null, draw the maps
it can be look like this :
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> {
double lat;
double long;
LatLng _pickedLoc;
Future _getLocation() async {
LocationData location = await Location().getLocation();
setState(() {
lat = location.latitude;
long = location.longitude;
});
}
_selectLocation(LatLng location) {
_pickedLoc = location;
}
#override
void initState() {
super.initState();
_getLocation();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: lat == null || long == null
? Center(
child: CircularProgressIndicator(),
)
: GoogleMap(
initialCameraPosition: CameraPosition(
zoom: 16,
target: LatLng(lat, long),
),
onTap: _selectLocation,
onCameraMove: (object) => {debugPrint(object.target.toString())},
markers: {
Marker(
markerId: MarkerId("m1"),
position: _pickedLoc,
)
},
),
);
}
}
I am new to fultter. I am trying to get real time of user's location. For this, I used the location plugin (https://pub.dev/packages/location).
The issue is that the map is being populated before the location get assigned, and returning an error:
The setter 'latitude' was called on null.
This is the main dart:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:location/location.dart';
import './models/userLocation.dart';
void main() => runApp(Maps());
class Maps extends StatefulWidget {
#override
_MapsState createState() => _MapsState();
}
class _MapsState extends State<Maps> {
LocationData currentLocation;
UserLocation _currentLocation;
var location = new Location();
String error;
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
GoogleMapController mapController;
void initState() {
super.initState();
initMapState();
}
initMapState() async {
try {
var userLocation = await location.getLocation();
_currentLocation = UserLocation(
latitude: userLocation.latitude,
longitude: userLocation.longitude,
);
} on PlatformException catch (e) {
if (e.code == 'PERMISSION_DENIED') {
error = 'Permission denied';
}
return _currentLocation;
}
location.onLocationChanged().listen((LocationData currentLocation) {
print(currentLocation.latitude);
print(currentLocation.longitude);
});
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Create new trip'),
backgroundColor: Colors.green[700],
),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target:
LatLng(_currentLocation?.latitude,_currentLocation?.longitude),
zoom: 11.0,
),
),
),
);
}
}
Below is the location model:
class UserLocation {
double latitude;
double longitude;
UserLocation({this.latitude, this.longitude});
}
Appreciate your support.
Thanks,
Edit:
Updated Working file:
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:location/location.dart';
import './models/userLocation.dart';
void main() => runApp(Maps());
class Maps extends StatefulWidget {
#override
_MapsState createState() => _MapsState();
}
class _MapsState extends State<Maps> {
Location location = new Location();
UserLocation userLocation;
StreamSubscription<LocationData> positionSubscription;
UserLocation _currentLocation;
String error;
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
GoogleMapController mapController;
#override
void initState() {
super.initState();
positionSubscription = location
.onLocationChanged()
.handleError((error) => print(error))
.listen(
(newPosition) => setState(() {
_currentLocation = UserLocation(
latitude: newPosition.latitude,
longitude: newPosition.longitude,
);
}),
);
}
#override
void dispose() {
positionSubscription?.cancel();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Create new trip'),
backgroundColor: Colors.green[700],
),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target:
LatLng(_currentLocation.latitude,_currentLocation.longitude),
zoom: 11.0,
),
),
),
);
}
}
So, because of your initState is not using #override this method is
not called
You can't use async calls in onInit callback. It is wrong. Again, you
missed #override.
According to docs You don't need to call getLocation because you
already have a subscription for locations.
Ideally, you need something like this:
UserLocation userPosition;
StreamSubscription<LocationData> positionSubscription;
#override
void initState() {
super.initState();
positionSubscription = location
.onLocationChanged()
.handleError((error) => print(error))
.listen(
(newPosition) => setState(() {
_currentLocation = UserLocation(
latitude: newPosition.latitude,
longitude: newPosition.longitude,
);
}),
);
}
#override
void dispose() {
positionSubscription?.cancel();
super.dispose();
}
write the super.initState() after the initMapState(); because after calling super.initState() The build() is directly called and will not wait for the initMapState() to complete its execution
void initState() {
initMapState();
super.initState();
}