https://pub.dev/packages/flutter_animarker
Wow, this is annoying. So Animarker is a Widget parent for my Google map. The map is busy with Markers. When the user needs to find a particular Marker from the drawer, they tap the item & it triggers a Ripple effect in the corresponding Marker.
The problem is it never stops rippling. It'll even attempt to animate several Markers if the user keeps on tapping.
It was love at first animation but I'm climbing the walls now!
Animarker(
isActiveTrip: rippleAnimationActive,
rippleRadius: 0.5, //[0,1.0] range, how big is the circle
rippleColor: Colors.teal, // Color of fade ripple circle
rippleDuration: Duration(milliseconds: 2500), //Pulse ripple duration
markers: animatedMarkerSet,
mapId: _mapController.future.then<int>((value) => value.mapId),
child: GoogleMap(
key: Key("myGoogleMap"),
mapType: MapType.hybrid,
initialCameraPosition: _edinburghCamera,
markers: _markers,
myLocationEnabled: true,
onMapCreated: (GoogleMapController controller) {
_mapController.complete(controller);
},
),
),
I trigger the animation in a Drawer item onTap():
onTap: () {
animatedMarkerSet = {
RippleMarker(
markerId: MarkerId(presentLocation.name),
position: presentLocation.latLng,
ripple: true) };
setState(() {
presentLocation = _location;
animatedMarkerSet;
rippleAnimationActive = true;
});
//setState(() => _markers.add(marker));
Navigator.of(context).pop();
},
You can see I've created a brand new Marker to animate, and added it to the animatedMarkerSet. This works fine.
When the user taps a Marker, any Marker, details about the location slide up. And I try to deactivate ANY Marker which is rippling. However no matter what I try it doesn't stop:
setState(() {
rippleAnimationActive = false;
animatedMarkerSet.clear(); // nuke from orbit
}
I've also tried changing the animatedMarkerSet to a Map, and attempting to deactivate the ripple using this:
void newLocationUpdate(LocationDetails oldLocation) {
var marker = RippleMarker(
markerId: MarkerId(oldLocation.name),
position: oldLocation.latLng,
ripple: false,
);
setState(() => animatedMarkerMap[MarkerId(oldLocation.name)] = marker);
}
But that doesn't work either.
I really really just need to switch the animation on and off. I don't see why Animarker's so resistant to setState(), telling it to stop.
In fact, the best thing might be to just have it run for 5 seconds then switch off, in all circumstances, but I fail to see how to do that either. Grrrr!
OK well I figured it out. AniMarker which takes the Set of animated Markers, is final. So once you hand it the set of say RippleMarkers, it'll animate them, but you can't then turn it off via a SetState() call.
I tried editing the AniMarker class, to make it not final, so you could mutate it's dataset, but I think because it's built on GoogleMap's Marker class, and they're final, it just will not work.
So AniMarker presently has limited utility.
My work around was just to mutate GoogleMaps marker: option, so I could highlight a Marker by changing it's color. It's also possible to change the circles: GoogleMap option to dyanically highlight a Marker according to user interaction.
Related
I'm using Flutter's sliding_up_panel & my app has a glitch.
I have a Googlemap as the back panel, When you select a location from the app drawer it animates the map camera to a marker, and the sliding up panel 'peeks', revealing the top of the panel, using the panel's minHeight: property. If the peek interests, the user can then choose to pull up to reveal more detail on the marker location, contained in a ListView.
The problem comes if the users selects a new location from the app drawer. The panel closes, the Map camera animates to the new marker, then the panel provides a 200px panel peek for the new location, but the scroll position is preserved from the prior panel's details. So I can have a peek that's supposed to show the title of the new Marker position, but in fact shows a slither of picture, or text half way down the panel.
I've tried using
slideUpPanelScrollController.jumpTo(0);
To jump the panel ListView to the top, but Android Studio Logcat says
ScrollController not attached to any scroll views.
'package:flutter/src/widgets/scroll_controller.dart':
Failed assertion: line 171 pos 12: '_positions.isNotEmpty'
Clearly, I don't understand how to attach SlidingPanel's ScrollController to the panel's ListView. My understanding of controllers could be improved.
Help appreciated.
SlidingUpPanel(
key: Key("slidingUpPanelKey"),
borderRadius: new BorderRadius.vertical(top: Radius.circular(8)),
parallaxEnabled: true,
controller: slidingPanelController,
onPanelOpened: () async {
setState(() {
panelMinHeight = 0;
});
},
onPanelClosed: () {
slideUpPanelScrollController.jumpTo(0);
},
minHeight: panelMinHeight,
maxHeight: MediaQuery.of(context).size.height - AppBar().preferredSize.height,
panelBuilder: (slideUpPanelScrollController) => _scrollingList(slideUpPanelScrollController, presentLocation),
body: Animarker(
// Other properties
curve: Curves.ease,
//markers: animatedMarkerMap.values.toSet(),
isActiveTrip: false,//rippleAnimationActive,
rippleRadius: 0.1, //[0,1.0] range, how big is the circle
rippleColor: myColorSwatch.gold, // Colors.teal Color of fade ripple circle
rippleDuration: Duration(milliseconds: 2600), //Pulse ripple duration
shouldAnimateCamera: false, // TODO stops weird camera centering movement?
mapId: _mapController.future.then<int>((value) => value.mapId),
child: GoogleMap(
key: Key("myGoogleMap"),
mapType: MapType.hybrid,
initialCameraPosition: _initialCameraPosition,
//TODO markers: _markers,
markers: animatedMarkerMap.values.toSet(),
circles: mapCircles, // used for highlighting a location selected from the drawer
myLocationEnabled: true,
zoomControlsEnabled: false, // TODO would prefer them on screen, but 1/2 off!
onMapCreated: (GoogleMapController controller) {
print("GoogleMaps onMapCreated fired");
_mapController.complete(controller);
},
),
),
),
I attach the ScrollController to the ListView here:
Widget _scrollingList(ScrollController slideUpPanelScrollController, LocationDetails presentLocation) {
return ListView(controller: slideUpPanelScrollController,
key: Key("scrollingPanelListView"),
children: [...
The Sliding Panel should show the top of it's ListView, with a draggable indicator, title, subtitle like so
But if I open a new location from the app drawer, squirting a new location's data into the panel, it doesn't reset the Panel's ScrollPosition, it maintains it, showing the user info half way down:
Did you attach the slideUpPanelScrollController to the ListView:
ListView(
controller: slideUpPanelScrollController
I think my issue is the same as here:
Flutter show marker's infoWindowText by default in Google map widget
However, there is no answer, except for a link to another post which isn't quite what I want to do.
When my map opens in my app, it shows the markers correctly, but I also want to have all the labels displaying by default on open...
As the shown by one of the markers here:
I'm creating markers like this:
for (Location location in _locations) {
final locationMarker = Marker(
markerId: MarkerId(location.id),
position: LatLng(location.geoY, location.geoX),
infoWindow: InfoWindow(
title: location.name,
),
onTap: () => _onTap(location),
icon: _mapMarkers.icon(location.slug),
draggable: false);
markers.add(locationMarker);
}
Then the map like this:
Widget _map(Set<Marker> markers) => GoogleMap(
mapType: MapType.normal,
initialCameraPosition: CameraPosition(target: widget.mapCentre),
markers: markers,
...
onMapCreated: (controller) => _onMapCreated(controller, markers),
);
And the in _onMapCreated, I've tried to show all the labels, but only the last in the list of markers is actually displayed:
_onMapCreated(GoogleMapController controller, Set<Marker> markers) {
if (mounted) {
setState(() {
_controller.complete(controller);
controller.setMapStyle(_mapStyle);
for (var marker in markers) {
controller.showMarkerInfoWindow(marker.markerId);
}
});
...
I'm using:
[{
"featureType": "poi",
"stylers": [
{
"visibility": "off"
}
]
}]
to remove points of interest from the maps and I am hoping I can do something similar to get marker labels to display by default, but so far I've not found anything when searching google, or that there's another solution.
You can use showMarkerInfoWindow property the GoogleMapController
final GoogleMapController controller = await _controller.future;
controller.showMarkerInfoWindow(MarkerId('ID_MARKET'));
I'm a novice in Flutter, and I encountered an issue with google maps plugin. I watched a couple of tutorials in order to get the current position of the camera and Most of them was using GoogleMapController.cameraPosition.target. I think they deleted this method from the controller(Since it is still on the development stage). Is there any other way of getting the current position of the camera?
If you are using the google_maps_flutter package:
The GoogleMap widget have the onCameraMove function that returns the CameraPosition while dragging the map or moving the camera.
To do this, you'll need to create a callback function called _getCameraPosition(CameraPosition cameraPosition which will be invoked when onCameraMove is called. For example:
void _getCameraPosition(CameraPosition cameraPosition) {
// You can do whatever you want with cameraPosition here
log("cameraPosition: " + cameraPosition.target.toString());
}
Then, you'll need to put the _getCameraPosition function to the onCameraMove field on GoogleMap widget, like this:
GoogleMap(
onCameraMove: _getCameraPosition, // pass it here
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: LatLng(-33.86882, 151.209296),
zoom: 12,
),
),
As a result, you will get a LatLng value in the debug console. For example:
cameraPosition: LatLng(-33.8940124943736, 151.2027569487691)
I'm pretty new in Flutter. It is amazing. I'm working on small app usign google maps. I have 6 points (Markers) and need to recognize which one was selected.
I've added ontap event into every marker with i-index (i = 0..5). When I tap/click on marker I always get 6. It should be 0..5 based on marker.
Thanx a lot, Gabriel
i=0;
marker.clear();
for (myPoint mar in globals.historia.items) {
print(i.toString());
marker.add(Marker(
markerId: MarkerId(i.toString()),
position: mar.pos,
draggable: false,
consumeTapEvents: true,
onTap: () {
print("Marker_id-${i.toString()}");
},
));
i++;
}
GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: myposition,
zoom: 17.0,
),
polylines: road,
markers: Set.of(marker),
)
When onTap() is triggered it calls i with its last value that's == 6, that's why every time you tap on a marker, the print method prints 6.
i is a global variable, that has its own address, so the print method will search for the value on that address every time onTap is called.
I propose this solution - replace youtr print method inside onTap with this : print("Marker_id-${globals.historia.items.indexOf(mar)}")
mar is a local variable inside the for in loop, and its value has never changed, so he will point on the same value, onTap will behave as you want.
I am trying to create a sample app like Uber with google_maps_flutter: ^0.5.10 .. In Uber app when you select a pickup/drop location, and you do double tap (to zoom in) or zoom in/zoom out scaling the screen it always happens respective to the center of screen. Whereas when I add the google maps in flutter and if I do double tap lets say on right bottom of screen, google maps zoom and takes the view to the area where it was tapped. Similarly it happens with the scaling (pinching screen). The area I scale the camera view goes to that particular location. But I want double tap or scaling to stay centered to my selected location (like in Uber).
I did achieve it using cameraMove and cameraStop callbacks. In that I determine if camera was moved due to a zoom, I get the last zoom factor and move camera back to my selected location with the new zoom factor. It works but does not looks good if I double tap on left corner the camera goes back to original position. Similarly I did for the scaling zoom as well to zoom in/zoom out the camera moves back to original location I selected.
Then I tried GestureDetector on top of the GoogleMaps. Inside that I handled the onDoubleTap. That looks neat as I just change the zoom factor on double tap and keep location same. But I am not able to achieve scaling zoom in/out using onScaleUpdate (etc) functions on GestureDetector.
Is there any better way in Google maps flutter plugin to do all this?
use onCameraMove this will listen to the change of the cameraPosition.
for instance if you zoom in using double tap or zoom in/out using gestures,
GoogleMap(
zoomGesturesEnabled: true,
tiltGesturesEnabled: false,
onCameraMove:(CameraPosition cameraPosition){
print(cameraPosition.zoom);
},
onCameraMove take a void function and pass to it the CameraPosition argument, so you can use
"cameraPosition.zoom" to return the current zoom level; "cameraPosition.tilt" return the current tilt angle ...
use zoomGesturesEnabled: true
like that :
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class ZoomInOutMaps extends StatefulWidget {
#override
_ZoomInOutMapsState createState() => _ZoomInOutMapsState();
}
class _ZoomInOutMapsState extends State<ZoomInOutMaps> {
Completer<GoogleMapController> _controller = Completer();
static const LatLng _center = const LatLng(45.521563, -122.677433);
void _onMapCreated(GoogleMapController controller) {
_controller.complete(controller);
}
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Zoom in and Out of Google Maps'),
backgroundColor: Colors.red,
),
body: GoogleMap(
//enable zoom gestures
zoomGesturesEnabled: true,
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
),
),
);
}
}
Use below for handling min and max zoom:
minMaxZoomPreference: MinMaxZoomPreference(13,17)