forked from flutter/plugins
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[google_maps_flutter] Add Marker drag events (flutter#2838)
- Loading branch information
1 parent
e69b50b
commit 588e89b
Showing
14 changed files
with
399 additions
and
6 deletions.
There are no files selected for viewing
4 changes: 4 additions & 0 deletions
4
packages/google_maps_flutter/google_maps_flutter/CHANGELOG.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
...ps_flutter/android/src/test/java/io/flutter/plugins/googlemaps/MarkersControllerTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
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); | ||
} | ||
} |
156 changes: 156 additions & 0 deletions
156
packages/google_maps_flutter/google_maps_flutter/example/lib/drag_marker.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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, | ||
), | ||
], | ||
), | ||
], | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.