Some phones, most notably the Samsung Galaxy Note line of devices, have styluses (styli?) that can be detected when they are close to the screen but not touching it. Can Flutter detect and handle that kind of event?
(what follows is my investigation on this, if you already know the answer, feel free to skip this )
The Listener class can detect actions performed with a stylus when it is touching the screen and the MouseRegion class is supposed to detect actions performed with a hovering pointer. So I wrote this simple widget to test both classes:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
String _message = "Nothing happened";
String _location = "Nothing happened";
void onEnter(PointerEnterEvent event) {
setState(() {
_message = "Pointer entered";
});
}
void onExit(PointerExitEvent event) {
setState(() {
_message = "Pointer exited";
});
}
void onHover(PointerHoverEvent event) {
setState(() {
_location = "Pointer at ${event.localPosition.dx} ${event.localPosition.dy} distance ${event.distance}";
});
}
void onDown(PointerDownEvent event) {
setState(() {
_message = "Pointer down";
});
}
void onUp(PointerUpEvent event) {
setState(() {
_message = "Pointer up";
});
}
void onMove(PointerMoveEvent event) {
setState(() {
_location = "Pointer moving at ${event.localPosition.dx} ${event.localPosition.dy} pressure ${event.pressure}";
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
children: [
MouseRegion(
onEnter: onEnter,
onExit: onExit,
onHover: onHover,
child: Listener(
onPointerDown: onDown,
onPointerUp: onUp,
onPointerMove: onMove,
child: Container(
width: 500,
height: 500,
color: Colors.red
)
)
),
Text(_message),
Text(_location)
]
)
),
);
}
}
Using a bluetooth mouse, when I move the pointer over the region, the MouseRegion
widget emits events, but when I do the same using the stylus, nothing happens.
However, the Listener
class does emit events when I touch the region with the stylus, and the event instances even include stylus-specific information like pressure. The PointerEvent class even includes a distance
field and according to its description, it is supposed to indicate the distance from the pointer to the screen, which seems to be precisely the feature I'm looking for.
This comment suggests that Flutter "is not ready" to support hoverable styluses, but he doesn't seem to be completely sure about it and it was posted a year ago, so maybe something changed.
Finally, when I hover the stylus over the screen while running the app, the following messages are shown on Android Studio's console:
D/ViewRootImpl(16531): updatePointerIcon pointerType = 20001, calling pid = 16531
D/InputManager(16531): setPointerIconType iconId = 20001, callingPid = 16531
So it does seem to detect something. It seems to me Flutter is actively discarding stylus related events and only handling mouse events since on the native side both mouse and pen actions can be handled by the MotionEvent class.
Am I missing something? Is there some other class that is able to handle that kind of event? Or some setting somewhere to enable it? Or is it really not possible at the moment?