-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Google maps marker drag events impl #2838
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
package io.flutter.plugins.googlemaps; | ||
|
||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.spy; | ||
import static org.mockito.Mockito.when; | ||
|
||
import com.google.android.gms.internal.maps.zzt; | ||
import com.google.android.gms.maps.GoogleMap; | ||
import com.google.android.gms.maps.model.LatLng; | ||
import com.google.android.gms.maps.model.Marker; | ||
import com.google.android.gms.maps.model.MarkerOptions; | ||
import io.flutter.plugin.common.BinaryMessenger; | ||
import io.flutter.plugin.common.MethodChannel; | ||
import io.flutter.plugin.common.MethodCodec; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
import org.junit.Test; | ||
import org.mockito.Mockito; | ||
|
||
public class MarkersControllerTest { | ||
|
||
@Test | ||
public void controller_OnMarkerDragStart() { | ||
final MethodChannel methodChannel = | ||
spy(new MethodChannel(mock(BinaryMessenger.class), "no-name", mock(MethodCodec.class))); | ||
final MarkersController controller = new MarkersController(methodChannel); | ||
final GoogleMap googleMap = mock(GoogleMap.class); | ||
controller.setGoogleMap(googleMap); | ||
|
||
final zzt z = mock(zzt.class); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is class Why not mock There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This may actually be very fragile if it's actually obfuscated code (with a name like that it could very well be). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for coming back to this one, I'll take a look at the new PR!! |
||
final Marker marker = new Marker(z); | ||
|
||
final String googleMarkerId = "abc123"; | ||
|
||
when(marker.getId()).thenReturn(googleMarkerId); | ||
when(googleMap.addMarker(any(MarkerOptions.class))).thenReturn(marker); | ||
|
||
final LatLng latLng = new LatLng(1.1, 2.2); | ||
final Map<String, String> markerOptions = new HashMap(); | ||
markerOptions.put("markerId", googleMarkerId); | ||
|
||
final List<Object> markers = Arrays.<Object>asList(markerOptions); | ||
controller.addMarkers(markers); | ||
controller.onMarkerDragStart(googleMarkerId, latLng); | ||
|
||
final List<Double> points = new ArrayList(); | ||
points.add(latLng.latitude); | ||
points.add(latLng.longitude); | ||
|
||
final Map<String, Object> data = new HashMap<>(); | ||
data.put("markerId", googleMarkerId); | ||
data.put("position", points); | ||
Mockito.verify(methodChannel).invokeMethod("marker#onDragStart", data); | ||
} | ||
|
||
@Test | ||
public void controller_OnMarkerDragEnd() { | ||
final MethodChannel methodChannel = | ||
spy(new MethodChannel(mock(BinaryMessenger.class), "no-name", mock(MethodCodec.class))); | ||
final MarkersController controller = new MarkersController(methodChannel); | ||
final GoogleMap googleMap = mock(GoogleMap.class); | ||
controller.setGoogleMap(googleMap); | ||
|
||
final zzt z = mock(zzt.class); | ||
final Marker marker = new Marker(z); | ||
|
||
final String googleMarkerId = "abc123"; | ||
|
||
when(marker.getId()).thenReturn(googleMarkerId); | ||
when(googleMap.addMarker(any(MarkerOptions.class))).thenReturn(marker); | ||
|
||
final LatLng latLng = new LatLng(1.1, 2.2); | ||
final Map<String, String> markerOptions = new HashMap(); | ||
markerOptions.put("markerId", googleMarkerId); | ||
|
||
final List<Object> markers = Arrays.<Object>asList(markerOptions); | ||
controller.addMarkers(markers); | ||
controller.onMarkerDragEnd(googleMarkerId, latLng); | ||
|
||
final List<Double> points = new ArrayList(); | ||
points.add(latLng.latitude); | ||
points.add(latLng.longitude); | ||
|
||
final Map<String, Object> data = new HashMap<>(); | ||
data.put("markerId", googleMarkerId); | ||
data.put("position", points); | ||
Mockito.verify(methodChannel).invokeMethod("marker#onDragEnd", data); | ||
} | ||
|
||
@Test | ||
public void controller_OnMarkerDrag() { | ||
final MethodChannel methodChannel = | ||
spy(new MethodChannel(mock(BinaryMessenger.class), "no-name", mock(MethodCodec.class))); | ||
final MarkersController controller = new MarkersController(methodChannel); | ||
final GoogleMap googleMap = mock(GoogleMap.class); | ||
controller.setGoogleMap(googleMap); | ||
|
||
final zzt z = mock(zzt.class); | ||
final Marker marker = new Marker(z); | ||
|
||
final String googleMarkerId = "abc123"; | ||
|
||
when(marker.getId()).thenReturn(googleMarkerId); | ||
when(googleMap.addMarker(any(MarkerOptions.class))).thenReturn(marker); | ||
|
||
final LatLng latLng = new LatLng(1.1, 2.2); | ||
final Map<String, String> markerOptions = new HashMap(); | ||
markerOptions.put("markerId", googleMarkerId); | ||
|
||
final List<Object> markers = Arrays.<Object>asList(markerOptions); | ||
controller.addMarkers(markers); | ||
controller.onMarkerDrag(googleMarkerId, latLng); | ||
|
||
final List<Double> points = new ArrayList(); | ||
points.add(latLng.latitude); | ||
points.add(latLng.longitude); | ||
|
||
final Map<String, Object> data = new HashMap<>(); | ||
data.put("markerId", googleMarkerId); | ||
data.put("position", points); | ||
Mockito.verify(methodChannel).invokeMethod("marker#onDrag", data); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
// Copyright 2013 The Flutter Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
// ignore_for_file: public_member_api_docs | ||
|
||
import 'dart:math'; | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:google_maps_flutter/google_maps_flutter.dart'; | ||
|
||
import 'page.dart'; | ||
|
||
class DragMarkerPage extends GoogleMapExampleAppPage { | ||
DragMarkerPage() : super(const Icon(Icons.drag_handle), 'Drag marker'); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return const DragMarkerBody(); | ||
} | ||
} | ||
|
||
class DragMarkerBody extends StatefulWidget { | ||
const DragMarkerBody(); | ||
|
||
@override | ||
State<StatefulWidget> createState() => DragMarkerBodyState(); | ||
} | ||
|
||
typedef MarkerUpdateAction = Marker Function(Marker marker); | ||
|
||
class DragMarkerBodyState extends State<DragMarkerBody> { | ||
DragMarkerBodyState(); | ||
static const LatLng center = LatLng(-33.86711, 151.1947171); | ||
|
||
GoogleMapController? controller; | ||
Map<MarkerId, Marker> markers = <MarkerId, Marker>{}; | ||
MarkerId? selectedMarker; | ||
int _markerIdCounter = 1; | ||
LatLng? markerPosition; | ||
|
||
void _onMapCreated(GoogleMapController controller) { | ||
this.controller = controller; | ||
} | ||
|
||
void _onMarkerTapped(MarkerId markerId) { | ||
final Marker? tappedMarker = markers[markerId]; | ||
if (tappedMarker != null) { | ||
setState(() { | ||
if (markers.containsKey(selectedMarker)) { | ||
final Marker resetOld = markers[selectedMarker]! | ||
.copyWith(iconParam: BitmapDescriptor.defaultMarker); | ||
markers[selectedMarker!] = resetOld; | ||
} | ||
selectedMarker = markerId; | ||
final Marker newMarker = tappedMarker.copyWith( | ||
iconParam: BitmapDescriptor.defaultMarkerWithHue( | ||
BitmapDescriptor.hueGreen, | ||
), | ||
); | ||
markers[markerId] = newMarker; | ||
}); | ||
} | ||
} | ||
|
||
void _onMarkerDrag(MarkerId markerId, LatLng newPosition) async { | ||
setState(() { | ||
this.markerPosition = newPosition; | ||
}); | ||
} | ||
|
||
void _add() { | ||
final int markerCount = markers.length; | ||
|
||
if (markerCount == 12) { | ||
return; | ||
} | ||
|
||
final String markerIdVal = 'marker_id_$_markerIdCounter'; | ||
_markerIdCounter++; | ||
final MarkerId markerId = MarkerId(markerIdVal); | ||
|
||
final Marker marker = Marker( | ||
draggable: true, | ||
markerId: markerId, | ||
position: LatLng( | ||
center.latitude + sin(_markerIdCounter * pi / 6.0) / 20.0, | ||
center.longitude + cos(_markerIdCounter * pi / 6.0) / 20.0, | ||
), | ||
infoWindow: InfoWindow(title: markerIdVal, snippet: '*'), | ||
onTap: () => _onMarkerTapped(markerId), | ||
onDrag: (LatLng position) => _onMarkerDrag(markerId, position), | ||
); | ||
|
||
setState(() { | ||
markers[markerId] = marker; | ||
}); | ||
} | ||
|
||
void _remove() { | ||
setState(() { | ||
if (markers.containsKey(selectedMarker)) { | ||
markers.remove(selectedMarker); | ||
} | ||
}); | ||
} | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Column( | ||
mainAxisAlignment: MainAxisAlignment.spaceEvenly, | ||
crossAxisAlignment: CrossAxisAlignment.stretch, | ||
children: <Widget>[ | ||
Expanded( | ||
child: Center( | ||
child: GoogleMap( | ||
onMapCreated: _onMapCreated, | ||
initialCameraPosition: const CameraPosition( | ||
target: center, | ||
zoom: 11.0, | ||
), | ||
markers: markers.values.toSet(), | ||
), | ||
), | ||
), | ||
Container( | ||
height: 30, | ||
padding: EdgeInsets.only(left: 12, right: 12), | ||
child: Row( | ||
mainAxisSize: MainAxisSize.max, | ||
children: [ | ||
markerPosition == null | ||
? Container() | ||
: Expanded(child: Text("lat: ${markerPosition!.latitude}")), | ||
markerPosition == null | ||
? Container() | ||
: Expanded(child: Text("lng: ${markerPosition!.longitude}")), | ||
], | ||
), | ||
), | ||
Row( | ||
children: <Widget>[ | ||
TextButton( | ||
child: const Text('add'), | ||
onPressed: _add, | ||
), | ||
TextButton( | ||
child: const Text('remove'), | ||
onPressed: _remove, | ||
), | ||
], | ||
), | ||
], | ||
); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ | |
// ignore_for_file: public_member_api_docs | ||
|
||
import 'package:flutter/material.dart'; | ||
import 'package:google_maps_flutter_example/drag_marker.dart'; | ||
import 'package:google_maps_flutter_example/lite_mode.dart'; | ||
import 'animate_camera.dart'; | ||
import 'map_click.dart'; | ||
|
@@ -34,6 +35,7 @@ final List<GoogleMapExampleAppPage> _allPages = <GoogleMapExampleAppPage>[ | |
PlacePolylinePage(), | ||
PlacePolygonPage(), | ||
PlaceCirclePage(), | ||
DragMarkerPage(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's another demo that deals with dragging markers, maybe this one can be merged into the PlaceMarkerPage (or the dragging demo of the PlaceMarkerPage can be moved to this one) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've merged them and add it to the PR #4400 |
||
PaddingPage(), | ||
SnapshotPage(), | ||
LiteModePage(), | ||
|
Uh oh!
There was an error while loading. Please reload this page.