Update Place Tracker to use latest version of plugin (#59)

pull/61/head
Kenzie Schmoll 6 years ago committed by GitHub
parent 8fe2999ee8
commit a2419b3dcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,10 @@
analyzer:
errors:
# treat missing required parameters as a warning (not a hint)
missing_required_param: warning
# treat missing returns as a warning (not a hint)
missing_return: warning
linter:
rules:
- unawaited_futures

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

@ -1,10 +1,12 @@
#include "AppDelegate.h"
#include "GeneratedPluginRegistrant.h"
#import "GoogleMaps/GoogleMaps.h"
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GMSServices provideAPIKey:@"YOUR KEY HERE"];
[GeneratedPluginRegistrant registerWithRegistry:self];
// Override point for customization after application launch.
return [super application:application didFinishLaunchingWithOptions:launchOptions];

@ -41,5 +41,7 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>io.flutter.embedded_views_preview</key>
<true/>
</dict>
</plist>

@ -25,6 +25,7 @@ class PlaceDetails extends StatefulWidget {
class PlaceDetailsState extends State<PlaceDetails> {
Place _place;
GoogleMapController _mapController;
final Set<Marker> _markers = {};
final TextEditingController _nameController = TextEditingController();
final TextEditingController _descriptionController = TextEditingController();
@ -39,7 +40,12 @@ class PlaceDetailsState extends State<PlaceDetails> {
void _onMapCreated(GoogleMapController controller) {
_mapController = controller;
_mapController.addMarker(MarkerOptions(position: _place.latLng));
setState(() {
_markers.add(Marker(
markerId: MarkerId(_place.latLng.toString()),
position: _place.latLng,
));
});
}
Widget _detailsBody() {
@ -74,6 +80,7 @@ class PlaceDetailsState extends State<PlaceDetails> {
center: _place.latLng,
mapController: _mapController,
onMapCreated: _onMapCreated,
markers: _markers,
),
const _Reviews(),
],
@ -210,6 +217,7 @@ class _Map extends StatelessWidget {
@required this.center,
@required this.mapController,
@required this.onMapCreated,
@required this.markers,
Key key,
}) : assert(center != null),
assert(onMapCreated != null),
@ -218,6 +226,7 @@ class _Map extends StatelessWidget {
final LatLng center;
final GoogleMapController mapController;
final ArgumentCallback<GoogleMapController> onMapCreated;
final Set<Marker> markers;
@override
Widget build(BuildContext context) {
@ -229,18 +238,17 @@ class _Map extends StatelessWidget {
height: 240.0,
child: GoogleMap(
onMapCreated: onMapCreated,
options: GoogleMapOptions(
cameraPosition: CameraPosition(
initialCameraPosition: CameraPosition(
target: center,
zoom: 16.0,
),
markers: markers,
zoomGesturesEnabled: false,
rotateGesturesEnabled: false,
tiltGesturesEnabled: false,
scrollGesturesEnabled: false,
),
),
),
);
}
}

@ -41,49 +41,55 @@ class PlaceMapState extends State<PlaceMap> {
return places.where((Place place) => place.category == category).toList();
}
GoogleMapController mapController;
Completer<GoogleMapController> mapController = Completer();
MapType _currentMapType = MapType.normal;
LatLng _lastMapPosition;
Map<Marker, Place> _markedPlaces = Map<Marker, Place>();
final Set<Marker> _markers = {};
Marker _pendingMarker;
MapConfiguration _configuration;
void onMapCreated(GoogleMapController controller) async {
mapController = controller;
mapController.onInfoWindowTapped.add(_onInfoWindowTapped);
mapController.complete(controller);
_lastMapPosition = widget.center;
// Draw initial place markers on creation so that we have something
// interesting to look at.
final Map<Marker, Place> places = await _markPlaces();
_zoomToFitPlaces(
setState(() {
for (Place place in AppState.of(context).places) {
_markers.add(_createPlaceMarker(place));
}
});
// Zoom to fit the initially selected category.
await _zoomToFitPlaces(
_getPlacesForCategory(
AppState.of(context).selectedCategory,
places.values.toList(),
_markedPlaces.values.toList(),
),
);
}
Future<Map<Marker, Place>> _markPlaces() async {
await Future.wait(
AppState.of(context).places.map((Place place) => _markPlace(place)));
return _markedPlaces;
}
Future<void> _markPlace(Place place) async {
final Marker marker = await mapController.addMarker(
MarkerOptions(
Marker _createPlaceMarker(Place place) {
final marker = Marker(
markerId: MarkerId(place.latLng.toString()),
position: place.latLng,
icon: _getPlaceMarkerIcon(place.category),
infoWindowText: InfoWindowText(
place.name,
'${place.starRating} Star Rating',
infoWindow: InfoWindow(
title: place.name,
snippet: '${place.starRating} Star Rating',
onTap: () => _pushPlaceDetailsScreen(place),
),
icon: _getPlaceMarkerIcon(place.category),
visible: place.category == AppState.of(context).selectedCategory,
),
);
_markedPlaces[marker] = place;
}
void _onInfoWindowTapped(Marker marker) {
_pushPlaceDetailsScreen(_markedPlaces[marker]);
return marker;
}
void _pushPlaceDetailsScreen(Place place) {
@ -120,55 +126,64 @@ class PlaceMapState extends State<PlaceMap> {
AppState.updateWith(context, places: newPlaces);
}
Future<void> _updateExistingPlaceMarker({@required Place place}) async {
void _updateExistingPlaceMarker({@required Place place}) {
Marker marker = _markedPlaces.keys
.singleWhere((Marker value) => _markedPlaces[value].id == place.id);
// Set marker visibility to false to ensure the info window is hidden. Once
// the plugin fully supports the Google Maps API, use hideInfoWindow()
// instead.
await mapController.updateMarker(
marker,
MarkerOptions(
visible: false,
),
);
await mapController.updateMarker(
marker,
MarkerOptions(
infoWindowText: InfoWindowText(
place.name,
setState(() {
final updatedMarker = marker.copyWith(
infoWindowParam: InfoWindow(
title: place.name,
snippet:
place.starRating != 0 ? '${place.starRating} Star Rating' : null,
),
visible: true,
),
);
_updateMarker(marker: marker, updatedMarker: updatedMarker, place: place);
});
}
_markedPlaces[marker] = place;
void _updateMarker({
@required Marker marker,
@required Marker updatedMarker,
@required Place place,
}) {
_markers.remove(marker);
_markedPlaces.remove(marker);
_markers.add(updatedMarker);
_markedPlaces[updatedMarker] = place;
}
void _switchSelectedCategory(PlaceCategory category) {
Future<void> _switchSelectedCategory(PlaceCategory category) async {
AppState.updateWith(context, selectedCategory: category);
_showPlacesForSelectedCategory(category);
await _showPlacesForSelectedCategory(category);
}
Future<void> _showPlacesForSelectedCategory(PlaceCategory category) async {
await Future.wait(
_markedPlaces.keys.map(
(Marker marker) => mapController.updateMarker(
marker,
MarkerOptions(
visible: _markedPlaces[marker].category == category,
),
),
),
setState(() {
for (Marker marker in List.of(_markedPlaces.keys)) {
final place = _markedPlaces[marker];
final updatedMarker = marker.copyWith(
visibleParam: place.category == category,
);
_zoomToFitPlaces(
_getPlacesForCategory(category, _markedPlaces.values.toList()));
_updateMarker(
marker: marker,
updatedMarker: updatedMarker,
place: place,
);
}
});
await _zoomToFitPlaces(_getPlacesForCategory(
category,
_markedPlaces.values.toList(),
));
}
void _zoomToFitPlaces(List<Place> places) {
Future<void> _zoomToFitPlaces(List<Place> places) async {
GoogleMapController controller = await mapController.future;
// Default min/max values to latitude and longitude of center.
double minLat = widget.center.latitude;
double maxLat = widget.center.latitude;
@ -182,7 +197,7 @@ class PlaceMapState extends State<PlaceMap> {
maxLong = max(maxLong, place.longitude);
}
mapController.animateCamera(
await controller.animateCamera(
CameraUpdate.newLatLngBounds(
LatLngBounds(
southwest: LatLng(minLat, minLong),
@ -194,40 +209,49 @@ class PlaceMapState extends State<PlaceMap> {
}
void _onAddPlacePressed() async {
Marker newMarker = await mapController.addMarker(
MarkerOptions(
position: LatLng(
mapController.cameraPosition.target.latitude,
mapController.cameraPosition.target.longitude,
),
setState(() {
final newMarker = Marker(
markerId: MarkerId(_lastMapPosition.toString()),
position: _lastMapPosition,
infoWindow: InfoWindow(title: 'New Place'),
draggable: true,
icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueGreen),
),
);
setState(() {
_markers.add(newMarker);
_pendingMarker = newMarker;
});
}
void _confirmAddPlace(BuildContext context) async {
if (_pendingMarker != null) {
await mapController.updateMarker(
_pendingMarker,
MarkerOptions(
icon: _getPlaceMarkerIcon(AppState.of(context).selectedCategory),
infoWindowText: InfoWindowText('New Place', null),
draggable: false,
),
);
// Create a new Place and map it to the marker we just added.
final Place newPlace = Place(
id: Uuid().v1(),
latLng: _pendingMarker.options.position,
name: _pendingMarker.options.infoWindowText.title,
latLng: _pendingMarker.position,
name: _pendingMarker.infoWindow.title,
category: AppState.of(context).selectedCategory,
);
_markedPlaces[_pendingMarker] = newPlace;
setState(() {
final updatedMarker = _pendingMarker.copyWith(
iconParam: _getPlaceMarkerIcon(AppState.of(context).selectedCategory),
infoWindowParam: InfoWindow(
title: 'New Place',
snippet: null,
onTap: () => _pushPlaceDetailsScreen(newPlace),
),
draggableParam: false,
);
_updateMarker(
marker: _pendingMarker,
updatedMarker: updatedMarker,
place: newPlace,
);
_pendingMarker = null;
});
// Show a confirmation snackbar that has an action to edit the new place.
Scaffold.of(context).showSnackBar(
@ -257,29 +281,25 @@ class PlaceMapState extends State<PlaceMap> {
);
AppState.updateWith(context, places: newPlaces);
setState(() {
_pendingMarker = null;
});
}
}
void _cancelAddPlace() {
if (_pendingMarker != null) {
mapController.removeMarker(_pendingMarker);
setState(() {
_markers.remove(_pendingMarker);
_pendingMarker = null;
});
}
}
void _onToggleMapTypePressed() {
final MapType nextType = MapType.values[
(mapController.options.mapType.index + 1) % MapType.values.length];
final MapType nextType =
MapType.values[(_currentMapType.index + 1) % MapType.values.length];
mapController.updateMapOptions(
GoogleMapOptions(mapType: nextType),
);
setState(() {
_currentMapType = nextType;
});
}
Future<void> _maybeUpdateMapConfiguration() async {
@ -297,16 +317,15 @@ class PlaceMapState extends State<PlaceMap> {
newConfiguration.selectedCategory) {
// If the configuration change is only a category change, just update
// the marker visibilities.
_showPlacesForSelectedCategory(newConfiguration.selectedCategory);
await _showPlacesForSelectedCategory(newConfiguration.selectedCategory);
} else {
// At this point, we know the places have been updated from the list
// view. We need to reconfigure the map to respect the updates.
await Future.wait(
newConfiguration.places
.where((Place p) => !_configuration.places.contains(p))
.map((Place value) => _updateExistingPlaceMarker(place: value)),
);
_zoomToFitPlaces(
.map((Place value) => _updateExistingPlaceMarker(place: value));
await _zoomToFitPlaces(
_getPlacesForCategory(
newConfiguration.selectedCategory,
newConfiguration.places,
@ -331,13 +350,13 @@ class PlaceMapState extends State<PlaceMap> {
children: <Widget>[
GoogleMap(
onMapCreated: onMapCreated,
options: GoogleMapOptions(
trackCameraPosition: true,
cameraPosition: CameraPosition(
initialCameraPosition: CameraPosition(
target: widget.center,
zoom: 11.0,
),
),
mapType: _currentMapType,
markers: _markers,
onCameraMove: (position) => _lastMapPosition = position.target,
),
_CategoryButtonBar(
selectedPlaceCategory: AppState.of(context).selectedCategory,

@ -12,7 +12,7 @@ dependencies:
cupertino_icons: ^0.1.2
google_maps_flutter: ^0.0.3
google_maps_flutter: ^0.4.0
uuid: 1.0.3

Loading…
Cancel
Save