how to animate google map view when change lat and lng? - google-maps

I added google map inside column.
my inspector like this:
Scaffold
- stack
- singlechildscrollview
- form
- container
- padding
- column
- sizedbox
- googlemap
SizedBox(
width: width,
height:height * .4,
child: GoogleMap(
gestureRecognizers: <Factory<OneSequenceGestureRecognizer>>[
Factory<OneSequenceGestureRecognizer>(
() => EagerGestureRecognizer())].toSet(),
mapType: MapType.normal,
initialCameraPosition: CameraPosition(
target: LatLng(lat, lng),
zoom: 15),
onCameraMove: (_)=>CameraPosition(
target: LatLng(lat, lng),
zoom: 15),
markers: Set<Marker>.of(<Marker>[
Marker(
markerId: MarkerId('id'),
position: LatLng(lat, lng),
icon: BitmapDescriptor.defaultMarker,
),
]),
onMapCreated: (GoogleMapController controller) {
setState(() {
controller.animateCamera(CameraUpdate.newLatLng(
LatLng(lat, lng),
));
});
},
)),
Google map search
RaisedButton(
onPressed: _handlePressButton,
child: Text("Search places"),
),
Future<void> _handlePressButton() async {
Prediction p = await PlacesAutocomplete.show(
context: context,
apiKey: kGoogleApiKey,
mode: Mode.overlay,
);
displayPrediction(p);
}
Future<void> displayPrediction(Prediction p) async {
if (p != null) {
PlacesDetailsResponse detail =
await _places.getDetailsByPlaceId(p.placeId);
setState(() {
lat = detail.result.geometry.location.lat;
lng = detail.result.geometry.location.lng;
});
}
}
After change lat and LNG map is not animated but the marker changed.. how to animate google map view?

this is how you would go about it
final GoogleMapController controller = await mapController;
mapCcontroller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
bearing: 0,
target: LatLng(lat, lon),
zoom: 16.0,
),
));

Related

Update marker in Google maps alertdialog in flutter

I am trying to load googlemap(google_maps_flutter 0.5.25+1
library) on a dialog window using the following method
_loadMapDialog() {
try {
if (_currentPosition.latitude == null) {
Toast.show("Location not available. Please wait...", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
_getLocation(); //_getCurrentLocation();
return;
}
_controller = Completer();
_userpos = CameraPosition(
target: LatLng(latitude, longitude),
zoom: 14.4746,
);
markers.add(Marker(
markerId: markerId1,
position: LatLng(latitude, longitude),
infoWindow: InfoWindow(
title: 'New Location',
snippet: 'Delivery Location',
)));
showDialog(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return AlertDialog(
title: Text("Select Your Location"),
titlePadding: EdgeInsets.all(5),
content: Text(curaddress),
actions: <Widget>[
Container(
height: screenHeight / 1.4 ?? 600,
width: screenWidth ?? 400,
child:
GoogleMap(
mapType: MapType.normal,
initialCameraPosition: _userpos,
markers: markers,
onMapCreated: (controller) {
_controller.complete(controller);
},
onTap: _loadLoc,
),
)
],
);
},
);
},
);
} catch (e) {
print(e);
return;
}
}
void _loadLoc(LatLng loc) async{
setState(() {
print("insetstate");
markers.clear();
latitude = loc.latitude;
longitude = loc.longitude;
label = latitude.toString();
_getLocationfromlatlng(latitude,longitude);
_home = CameraPosition(
target: loc,
zoom: 14,
);
markers.add(Marker(
markerId: markerId1,
position: LatLng(latitude, longitude),
infoWindow: InfoWindow(
title: 'New Location',
snippet: 'Delivery Location',
)));
});
_userpos = CameraPosition(
target: LatLng(latitude, longitude),
zoom: 14.4746,
);
_newhomeLocation();
}
Future<void> _newhomeLocation() async {
gmcontroller = await _controller.future;
gmcontroller.animateCamera(CameraUpdate.newCameraPosition(_home));
Navigator.of(context).pop(false);
_loadMapDialog();
}
I did manage to load the map in my AlertDialog. The problem is I need to be able to select new location on the map remove the previous marker and show new marker on the map, however marker is not showing on the map unless the app perform hot reload. For now I'm using kind a stupid way which pop the current alertdialog and show it again using _loadMapDialog() method to reload widget. I did try to use flutter_places_dialog library but seems I got some problem with activity return result error.
flutter newb here be kind..
Problem is you are updating marker with setState provided by StatefulWidget.
But Dialog is updating its state with setState provided by StatefulBuilder.
Solution is add StatefulBuilder's setState to onTap callback function's parameter and use it inside _loadLoc function like my code.
List<Marker> markers = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('GoogleMap'),
),
body: Center(
child: RaisedButton(
onPressed: () {
showDialog(
context: (context),
builder: (context) {
return StatefulBuilder(builder: (context, newSetState) {
return AlertDialog(
title: Text('Google Map'),
content: GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(11.004556, 76.961632), zoom: 14),
markers: markers.toSet(),
onTap: (newLatLng) {
addMarker(newLatLng, newSetState);
},
),
);
});
});
},
),
),
);
addMarker(latLng, newSetState)
{
newSetState(() {
markers.clear();
markers.add(Marker(markerId: MarkerId('New'), position: latLng));
});
}

Flutter: How to place the mylocation button on Google Maps at different positions?

I'm using Google Maps and by default the myLocation button shows up on the topRight corner. I want it at the bottom right corner.
I can't seem to have any property inside GoogleMap widget
GoogleMap(
myLocationEnabled: true,
myLocationButtonEnabled: true,
initialCameraPosition: CameraPosition(
target: _currentLocation,
zoom: 11.0,
),
onMapCreated: _onMapCreated,
),
Try using FloationgButton
GoogleMap(
mapType: MapType.hybrid,
initialCameraPosition: _kGooglePlex,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
myLocationEnabled: true,
),
floatingActionButton: FloatingActionButton.extended(
onPressed: _currentLocation,
label: Text('My Location'),
icon: Icon(Icons.location_on),
),
);
}
also set with the current location
void _currentLocation() async {
final GoogleMapController controller = await _controller.future;
LocationData currentLocation;
var location = new Location();
try {
currentLocation = await location.getLocation();
} on Exception {
currentLocation = null;
}
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
bearing: 0,
target: LatLng(currentLocation.latitude, currentLocation.longitude),
zoom: 17.0,
),
));
}

Flutter -> loading google maps in background

I need to load maps in background because when I hit the tab with maps.dart for the first time, map is loading. It is looking bad so I want to use FutureBuilder to show CircularProgressIndicator() but I have no idea how to do this.
I know how to do it with Lists but in this case...
This maps.dart code:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
class Maps extends StatefulWidget {
#override
_MapsState createState() => _MapsState();
}
class _MapsState extends State<Maps> with AutomaticKeepAliveClientMixin {
Completer<GoogleMapController> _controller = Completer();
#override
void initState() {
super.initState();
}
double zoomValue = 9.0;
#override
Widget build(BuildContext context) {
super.build(context);
return Scaffold(
body: Stack(
children: <Widget>[
_buildGoogleMap(context),
_zoomMinusFunction(),
_zoomPlusFunction(),
],
),
);
}
Widget _zoomMinusFunction() {
return Align(
alignment: Alignment.topLeft,
child: IconButton(
icon: Icon(FontAwesomeIcons.searchMinus, color: Color(0xff6200ee)),
onPressed: () {
zoomValue--;
_minus(zoomValue);
}),
);
}
Widget _zoomPlusFunction() {
return Align(
alignment: Alignment.topRight,
child: IconButton(
icon: Icon(FontAwesomeIcons.searchPlus, color: Color(0xff6200ee)),
onPressed: () {
zoomValue++;
_plus(zoomValue);
}),
);
}
Future<void> _minus(double zoomValue) async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(target: LatLng(x, y), zoom: zoomValue)));
}
Future<void> _plus(double zoomValue) async {
final GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(target: LatLng(x, y), zoom: zoomValue)));
}
Widget _buildGoogleMap(BuildContext context) {
return Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
mapType: MapType.normal,
initialCameraPosition:
CameraPosition(target: LatLng(x, y), zoom: 9),
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
markers: {
aaa,
bbb,
},
),
);
}
#override
bool get wantKeepAlive => true;
}
Marker aaa = Marker(
markerId: MarkerId('aaa'),
position: LatLng(x, y),
infoWindow: InfoWindow(title: 'aaa', snippet: 'aaa'),
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueViolet,
),
);
Marker bbb = Marker(
markerId: MarkerId('bbb'),
position: LatLng(x, y),
infoWindow:
InfoWindow(title: 'bbb', snippet: 'bbb'),
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueViolet,
),
);
Sorry, I'm new to Flutter.
I know this is a little late, but if it still helps, this is what I have done.
_userLocation == null // If user location has not been found
? Center(
// Display Progress Indicator
child: CircularProgressIndicator(
backgroundColor: UniColors.primaryColour[500],
),
)
: GoogleMap(
// Show Campus Map
onMapCreated: _onMapCreated,
initialCameraPosition: // required parameter that sets the starting camera position. Camera position describes which part of the world you want the map to point at.
CameraPosition(
target: _userLocation,
zoom: defaultZoom,
tilt: 0.0),
scrollGesturesEnabled: true,
tiltGesturesEnabled: true,
trafficEnabled: false,
indoorViewEnabled: true,
compassEnabled: true,
rotateGesturesEnabled: true,
myLocationEnabled: true,
mapType: _currentMapType,
zoomGesturesEnabled: true,
cameraTargetBounds: new CameraTargetBounds(
new LatLngBounds(
northeast: uniCampusNE,
southwest: uniCampusSW,
),
),
minMaxZoomPreference:
new MinMaxZoomPreference(minZoom, maxZoom),
),

How does drop pins with long press on google map with flutter?

I'm new to flutter.
I'm trying to drop pins on map with flutter,
Here I got the current location with geolocator package and set a marker
GoogleMap(
onMapCreated: (controller){
mapController=controller ;
},
mapType: _currentMapType,
myLocationEnabled: true,
initialCameraPosition: CameraPosition(
target:_center,
zoom: 11.0,
),
markers: {
//Marker for current Location
Marker(
markerId: MarkerId("marker"),
position: LatLng(currentPosition.latitude, currentPosition.longitude),
infoWindow: InfoWindow(title: 'Current Location'),
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed)
)
},
),
I was recently working on this code, it may help you.
1.- First define the markers in this way (do it as a global variable):
Map<MarkerId, Marker> markers = <MarkerId, Marker>{};
2.- Create the Google Maps widget:
#override
Widget build(BuildContext context) {
return new Scaffold(
body: Stack(
children: [Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: GoogleMap(
mapType: _defaultMapType,
myLocationEnabled: true,
myLocationButtonEnabled: true,
initialCameraPosition: _currentposition,
onMapCreated: (GoogleMapController controller) {
_controller.complete(controller);
},
compassEnabled: true,
tiltGesturesEnabled: false,
onLongPress: (latlang) {
_addMarkerLongPressed(latlang); //we will call this function when pressed on the map
},
markers: Set<Marker>.of(markers.values), //all markers are here
)
)]
),
);
}
3.- Create the function (method) '_addMarkerLongPressed':
Future _addMarkerLongPressed(LatLng latlang) async {
setState(() {
final MarkerId markerId = MarkerId("RANDOM_ID");
Marker marker = Marker(
markerId: markerId,
draggable: true,
position: latlang, //With this parameter you automatically obtain latitude and longitude
infoWindow: InfoWindow(
title: "Marker here",
snippet: 'This looks good',
),
icon: BitmapDescriptor.defaultMarker,
);
markers[markerId] = marker;
});
//This is optional, it will zoom when the marker has been created
GoogleMapController controller = await _controller.future;
controller.animateCamera(CameraUpdate.newLatLngZoom(latlang, 17.0));
}
I hope I've helped :)

Fix google map marker in center

In my flutter app. I am using google_maps_plugin . The link is https://github.com/flutter/plugins/tree/master/packages/google_maps_flutter .
I want to fix the marker in center of map without movable after draging the map.
I want it likes http://jsfiddle.net/UuDA6/
In my code i am using MarkerOption for placing the marker.
MarkerOptions options = new MarkerOptions(
alpha: 1.0,
anchor: Offset(0.5, 1.0),
consumeTapEvents: false,
draggable: false,
flat: false,
icon: BitmapDescriptor.defaultMarker,
infoWindowAnchor: Offset(0.5, 0.0),
infoWindowText: InfoWindowText.noText,
position: LatLng(17.411439, 78.5486697),
rotation: 0.0,
visible: true,
zIndex: 0.0,
);
But in the position i want to know how to give the center of map.
If any one have idea about it please share it.
Actually with new update of google_maps_flutter: ^0.4.0 we can achieve above requirement easily.
This is the demo link.
Map<MarkerId, Marker> _markers = <MarkerId, Marker>{};
int _markerIdCounter = 0;
Completer<GoogleMapController> _mapController = Completer();
Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: GoogleMap(
markers: Set<Marker>.of(_markers.values),
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: Constants.LOCATION_SRI_LANKA,
zoom: 12.0,
),
myLocationEnabled: true,
onCameraMove: (CameraPosition position) {
if(_markers.length > 0) {
MarkerId markerId = MarkerId(_markerIdVal());
Marker marker = _markers[markerId];
Marker updatedMarker = marker.copyWith(
positionParam: position.target,
);
setState(() {
_markers[markerId] = updatedMarker;
});
}
},
),
)
void _onMapCreated(GoogleMapController controller) async {
_mapController.complete(controller);
if ([INITIAL_LOCATION] != null) {
MarkerId markerId = MarkerId(_markerIdVal());
LatLng position = [INITIAL_LOCATION];
Marker marker = Marker(
markerId: markerId,
position: position,
draggable: false,
);
setState(() {
_markers[markerId] = marker;
});
Future.delayed(Duration(seconds: 1), () async {
GoogleMapController controller = await _mapController.future;
controller.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: position,
zoom: 17.0,
),
),
);
});
}
}
String _markerIdVal({bool increment = false}) {
String val = 'marker_id_$_markerIdCounter';
if (increment) _markerIdCounter++;
return val;
}
This is based on the #Joe answer but it has more accurated pin position and no other class is required:
double mapWidth = MediaQuery.of(context).size.width;
double mapHeight = MediaQuery.of(context).size.height - 215;
double iconSize = 40.0;
return new Stack(
alignment: Alignment(0.0, 0.0),
children: <Widget>[
new Container(
width: mapWidth,
height: mapHeight,
child: _googleMap
),
new Positioned(
top: (mapHeight - iconSize)/ 2,
right: (mapWidth - iconSize)/ 2,
child: new Icon(Icons.person_pin_circle, size: iconSize),
)
]);
This solution don't require to repaint the entire Screen (no setState call) when user update the position. You won't see that weird marker "movement".
The right answer is to use Stack and overlay marker pin on map. if you try to put marker on map using GoogleMaps markers property, you have to update marker position on CameraMove and call setState which add latency on redrawing maker.
compare two approaches:
class StoreLocationMap extends StatefulWidget {
final Coordinate userLocation;
const StoreLocationMap({Key? key, required this.userLocation})
: super(key: key);
#override
_StoreLocationMapState createState() => _StoreLocationMapState();
}
class _StoreLocationMapState extends State<StoreLocationMap> {
final List<Marker> _markers = [];
#override
Widget build(BuildContext context) {
return Stack(
alignment: Alignment.center,
children: [
GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(
widget.userLocation.latitude, widget.userLocation.longitude),
zoom: 14),
markers: _markers.toSet(),
onMapCreated: (controller) {
final marker = Marker(
markerId: MarkerId('0'),
position: LatLng(
widget.userLocation.latitude, widget.userLocation.longitude),
);
_markers.add(marker);
},
onCameraMove: (position) {
setState(() {
_markers.first =
_markers.first.copyWith(positionParam: position.target);
});
},
),
Image.asset(
'assets/images/delivery-area-start-pin.png',
frameBuilder: (context, child, frame, wasSynchronouslyLoaded) {
return Transform.translate(
offset: const Offset(8, -37),
child: child,
);
},
)
],
);
}
}
As my custom marker has shadow and is not symmetric, I used Transform widget to translate custom marker to point to right location.
How to get map center coordinate? or center maker position?
User onCameraMove to get map center position:
onCameraMove: (position) {
print(position.target);
},
It is possible using stack. The code is shown below.
Stack(
children: <Widget>[
GoogleMap(
onMapCreated: _onMapCreated,
),
InfoView()
],)
The InfoView is
class InfoView extends State<AppPage> {
const InfoView({
Key key,
}) : super(key: key);
#override
Widget build(BuildContext context) {
return new Align(
alignment: Alignment.center,
child: new Icon(Icons.person_pin_circle, size: 40.0),
);
}
}
Then the _onMapCreated is
void _onMapCreated(GoogleMapController controller) {
setState(() {
mapController = controller;
mapController.animateCamera(CameraUpdate.newCameraPosition(
CameraPosition(
bearing: 270.0,
target: LatLng(lattitude, longitude),
tilt: 30.0,
zoom: 17.0,
),
));
});
}
}
This stack class is useful if you want to overlap several children in a simple way, for example having some text and an image, overlaid with a gradient and a button attached to the bottom.
I recommend to you to try this new Flutter package https://pub.dev/packages/flutter_animarker
Use Stack and IgnorePointer to ignore touches on your widget
Stack(
children: <Widget>[
GoogleMap(
....
),
Center(
child: IgnorePointer(
child: ...
)
)
]
)