Layer Interactivity
Layer interactivity is different to map interactivity. See Interaction Options to control map interactivity.
For information about how hit testing behaves in flutter_map, see Hit Testing Behaviour.
It is important to note that hit testing != interactivity, and hit testing is always executed on interactable layers by default.
The following layers are interactable - they have specialised hitTest
ers and support external hit detection:
These all follow roughly the same pattern to setup hit detection/interactivity, and there's three or four easy steps to setting it up.
1. Attach A Hit Notifier
Direct callbacks, such as onTap,
aren't provided on layers or individual elements, to maximize flexibility.
Pass a LayerHitNotifier
to the hitNotifier
parameter of the layer. The LayerHitNotifier
should be created as a ValueNotifier
defaulting to null
, but strongly typed to LayerHitNotifier
.
This notifier will be notified whenever a hit test occurs on the layer, with a LayerHitResult
when an element (such as a Polyline
or Polygon
) within the layer is hit, and with null
when an element is not hit (but the layer is).
It is possible to listen to the notifier directly with addListener
, if you want to handle all hit events (including, for example, hover events).
However, most use cases just need to handle particular gestures (such as taps). This can be done with a wrapper widget to 'filter' the events appropriately: 3. Gesture Detection.
2. Add hitValue
To Elements
hitValue
To ElementsTo identify which particular element was hit (which will be useful when handling the hit events in later steps), supported elements have a hitValue
property.
This can be set to any object, but if one layer contains all the same type, type casting can be avoided (if the type is also specified in the LayerHitNotifier
's type argument).
The equality of the element depends on the equality of the hitValue
.
Therefore, any object passed to the hitValue
should have a valid and useful equality method.
Objects such as records do this behind the scenes, and can be a good choice to store small amounts of uncomplicated data alongside the element.
3. Gesture Detection
To only handle certain hits based on the type of gesture the user performed (such as a tap), wrap the layer with a gesture/hit responsive widget, such as GestureDetector
or MouseRegion
.
These widgets are smart enough to delegate whether they detect a hit (and therefore whether they can detect a gesture) to the child - although HitTestBehavior.deferToChild
may be required for some widgets to enable this functionality.
This means the layer can report whether it had any form of hit, and the handler widget can detect whether the gesture performed on it actually triggered a hit on the layer below.
4. Hit Handling
Once a LayerHitResult
object is obtained, through the hit notifier, you can retrieve:
hitValues
: thehitValue
s of all elements that were hit, ordered by their corresponding element, first-to-last, visually top-to-bottomcoordinate
: the geographic coordinate of the hit location (which may not lie on any element)point
: the screen point of the hit location
If all the hitValue
s in a layer are of the same type, and the created hit notifier specifies that type in the type argument, typing is preserved all the way to retrieval.
Because the HitNotifier
is a special type of ValueNotifier
, it can be both listened to (like a Stream
), and its value instantly retrieved (like a normal variable).
Therefore, there are two ways to retrieve a LayerHitResult
(or null
) from the notifier:
Using
.value
to instantly retrieve the value This is usually done within a gesture handler, such asGestureDetector.onTap
, as demonstrated below.Adding a listener (
.addListener
) to retrieve all hit results This is useful where you want to apply some custom/advanced filtering to the values, and is not a typical usecase.