gpt4 book ai didi

android - Flutter 可以检测到悬停的手写笔吗?

转载 作者:行者123 更新时间:2023-12-03 13:29:52 44 4
gpt4 key购买 nike

一些手机,尤其是三星 Galaxy Note 系列设备,有手写笔(手写笔?),当它们靠近屏幕但​​不触摸时可以检测到。 Flutter 可以检测和处理这种事件吗?
(以下是我对此的调查,如果你已经知道答案,请随意跳过这个😄)
Listener类可以检测触控笔在触摸屏幕时执行的操作,MouseRegion类应该检测使用悬停指针执行的操作。所以我写了这个简单的小部件来测试这两个类:

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)
]
)
),
);
}
}
使用蓝牙鼠标,当我将指针移到该区域上时, MouseRegion小部件发出事件,但是当我使用手写笔执行相同操作时,什么也没有发生。
但是, Listener当我 时,类确实会发出事件触摸 触控笔所在的区域,事件实例甚至包括触控笔特定的信息,如压力。 PointerEvent类甚至包括 distance字段,根据它的描述,它应该指示从指针到屏幕的距离,这似乎正是我正在寻找的功能。
This comment暗示 Flutter“还没有准备好”支持可悬停的手写笔,但他似乎并不完全确定这一点,而且它是在一年前发布的,所以也许有些事情发生了变化。
最后,当我在运行应用程序时将触控笔悬停在屏幕上时,Android Studio 的控制台上会显示以下消息:
D/ViewRootImpl(16531): updatePointerIcon pointerType = 20001, calling pid = 16531
D/InputManager(16531): setPointerIconType iconId = 20001, callingPid = 16531
所以它似乎确实检测到了一些东西。在我看来,Flutter 正在积极丢弃与手写笔相关的事件,只处理鼠标事件,因为在 native 端,鼠标和笔的 Action 都可以由 MotionEvent 处理。类(class)。
我错过了什么吗?是否有其他类能够处理这种事件?或者在某处启用它的一些设置?还是目前真的不可能?

最佳答案

我希望在十分钟内有人会来这里说“哦,你可以使用这个类,你不知道如何使用谷歌吗?”,但显然情况并非如此。所以我决定研究一下 Flutter 的源代码。
所以我从MouseRegion开始类,它使用 _RawMouseRegion , 它使用 RenderMouseRegion .然后,它使用 MouseTrackerAnnotation 注册一些事件处理回调。 .该类的实例被 MouseTracker 拾取。 ,谁接收指针事件并调用所有对它们感兴趣的回调。这是在 _handleEvent 中完成的。函数,其前两行是:

if (event.kind != PointerDeviceKind.mouse)
return;
所以我想我找到了罪魁祸首。只需添加 PointerDeviceKind.stylus 即可解决此问题。到那个 if陈述。或者,也许这样做会使地球开始倒转或其他什么。 GitHub 问题可能是获得答案的最佳地点。
但并非全部丢失。 MouseTracker类从 PointerRouter 获取其事件,其单例实例在 GestureBinding.instance.pointerRouter 可用. PointerRouter有一个 addGlobalRoute允许您注册自己的回调以接收事件的方法,其中包括 MouseTracker 的触控笔事件正在忽略。
我确信这不是推荐的做事方式,因为它绕过了 Flutter 的许多内部内容,而这些内容可能是有原因的。但是,虽然没有“官方”的做事方式(而且我怀疑这个非常具体的用例远不及他们的优先级列表的顶部),但可以通过这种方式解决它。嘿,我什至找到了 regular widget使用 PointerRouter也是直接的,所以它可能不是太危险。
Activity PointerRouter给你的不如 MouseRegion的方便,因为它的位置在全局坐标中。但是你可以得到 RenderBox您的小部件并使用 globalToLocal将位置转换为局部坐标。这是一个小的工作示例:
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
//We'll use the render box of the object with this key to transform the event coordinates:
GlobalKey _containerKey = GlobalKey();
//Store the render box:
//(The method to find the render box starts with "find" so I suspect it is doing
//some non trivial amount of work, so instead of calling it on every event, I'll
//just store the renderbox here):
RenderBox _rb;
String _message = "Nothing happened";

_MyHomePageState() {
//Register a method to receive the pointer events:
GestureBinding.instance.pointerRouter.addGlobalRoute(_handleEvent);
}

@override
void dispose() {
//See? We're even disposing of things properly. What an elegant solution.
super.dispose();
GestureBinding.instance.pointerRouter.removeGlobalRoute(_handleEvent);
}

//We'll receive all the pointer events here:
void _handleEvent(PointerEvent event) {
//Make sure it is a stylus event:
if(event.kind == PointerDeviceKind.stylus && _rb != null) {
//Convert to the local coordinates:
Offset coords = _rb.globalToLocal(event.position);

//Make sure we are inside our component:
if(coords.dx >= 0 && coords.dx < _rb.size.width && coords.dy >= 0 && coords.dy < _rb.size.height) {
//Stylus is inside our component and we have its local coordinates. Yay!
setState(() {
_message = "dist=${event.distance} x=${coords.dx.toStringAsFixed(1)} y=${coords.dy.toStringAsFixed(1)}";
});
}
}
}

@override
void initState() {
//Doing it this way, as suggested by this person: https://medium.com/@diegoveloper/flutter-widget-size-and-position-b0a9ffed9407
WidgetsBinding.instance.addPostFrameCallback(_afterLayout);
super.initState();
}

_afterLayout(_) {
_rb = _containerKey.currentContext.findRenderObject();
}

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
//Event position will be converted to this container's local coordinate space:
key: _containerKey,
width: 200,
height: 200,
color: Colors.red
),
Text(_message)
]
)
),
);
}
}

关于android - Flutter 可以检测到悬停的手写笔吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63024698/

44 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com