[英]How do I detect if a GestureDetector is hovered in Flutter?
The MouseRegion鼠标区
The MouseRegion Widget MouseRegion exposes a few events related to, you guessed it, your mouse. MouseRegion 小部件 MouseRegion 公开了一些与鼠标相关的事件,您猜对了。 These events are:
这些事件是:
OnEnter, which will trigger when your mouse enters the Widget.
OnExit, which will trigger when your mouse leaves the Widget.
OnHover, which will trigger both when your mouse enters the Widget and on every subsequent move inside the Widget.
All of these actually are PointerEvents which return all sorts of informations regarding the user's pointer.所有这些实际上都是 PointerEvents,它返回有关用户指针的各种信息。 Here, we're going to be looking at the current position of the user's mouse inside the containing Widget which is stored under the guise of an Offset.
在这里,我们将查看用户鼠标在包含 Widget 中的当前 position,该 Widget 以 Offset 的名义存储。
class _MyHoverableWidgetState extends State<MyHoverableWidget>{
// Our state
bool amIHovering = false;
Offset exitFrom = Offset(0,0);
return MouseRegion(
onEnter: (PointerDetails details) => setState(() => amIHovering = true),
onExit: (PointerDetails details) => setState(() {
amIHovering = false;
exitFrom = details.localPosition; // You can use details.position if you are interested in the global position of your pointer.
}),
child: Container(
width: 200,
height: 200,
child: Center(
child:Text(amIHovering ? "Look mom, I'm hovering" : "I exited from: $exitFrom"),
),
),
);
}
For anyone looking to do this on mobile , note that a touch interface doesn't actually handle the concept of "hover" unlike your desktop browser, so solutions proposing MouseRegion.onHover|Enter|Exit
, Inkwell.onHover
, or Listener.onPointerHover
that look ok fiddling in eg DartPad will not be responsive or otherwise behave oddly in your device/simulators (ie MouseRegion.onHover
will fire on a tap for mobile, which may be confusing if you didn't read the property closely).对于希望在移动设备上执行此操作的任何人,请注意触摸界面实际上并不处理“悬停”的概念,这与您的桌面浏览器不同,因此建议
MouseRegion.onHover|Enter|Exit
、 Inkwell.onHover
或Listener.onPointerHover
的解决方案看起来不错,例如 DartPad 中的摆弄将不会响应或在您的设备/模拟器中表现奇怪(即MouseRegion.onHover
将在点击移动设备时触发,如果您没有仔细阅读该属性,这可能会造成混淆)。
Solutions for mobile that involve using a Listener.onPointerMove
and manually hitTesting the RenderBox
for the selection area has been discussed here and again here .涉及使用
Listener.onPointerMove
和手动点击测试选择区域的RenderBox
的移动解决方案已在此处和此处再次讨论。 (The latter also has an answer that explicitly calculates it yourself using Rect
s representing the bounding boxes in the global coordinate frame for whatever you want to hit. Presumably Path.contains
could be used to do the same for non-rectangular hit zones.) (后者也有一个答案,使用
Rect
s 自己明确计算它,代表全局坐标系中的边界框,无论你想击中什么。大概Path.contains
可以用来对非矩形击中区域做同样的事情。)
You can create a really small box and move it along when dragging, then implement some collision (this package: https://pub.dev/packages/slowly_moving_widgets_field ), and check whether your small box is collide with GestureDetector's box or not.您可以创建一个非常小的盒子并在拖动时将其移动,然后实现一些碰撞(此 package: https://pub.dev/packages/slowly_moving_widgets_field ),并检查您的小盒子是否与 GestureDetector 碰撞。
If it's collide -> return hovered If it's not -> not hovered如果碰撞 -> 返回悬停 如果不是 -> 未悬停
I'm not familiar with a method for doing this with GestureDetector since I believe all gestures need to start inside the GestureDetector widget.我不熟悉使用 GestureDetector 执行此操作的方法,因为我相信所有手势都需要在 GestureDetector 小部件内开始。 It may be possible to wrap a container inside a GestureDetector and determine when the pointer is over top of the container.
可以将容器包装在 GestureDetector 中并确定指针何时位于容器顶部。
If you're trying to do this on a Web or desktop device, you can use MouseRegion widget.如果您尝试在 Web 或桌面设备上执行此操作,则可以使用MouseRegion小部件。 If you go to the link, you can see how easily it detects mouse entries and exits.
如果您将 go 链接到该链接,则可以看到它检测鼠标进入和退出的难易程度。
There's also the Draggable widget that can be used in conjunction with the DraggableTarget widget to do some cool things.还有可以与DraggableTarget小部件结合使用的 Draggable 小部件来做一些很酷的事情。
Unfortunately you can't use GestureDetecture
for that, instead you have to use MouseRegion
.不幸的是,您不能为此使用
GestureDetecture
,而是必须使用MouseRegion
。
I'm using the idea of that answer but I will correct it, because it doesn't work (for me).我正在使用该答案的想法,但我会纠正它,因为它不起作用(对我来说)。 The answer used
PointerDetails
which does not work for me.答案使用了对我不起作用的
PointerDetails
。 Instead I will use PointerEvent
.相反,我将使用
PointerEvent
。
// inside your current widget
class _MyHoverableWidgetState extends State<MyHoverableWidget>{
// some previous code of your class //
// define a class variable to store the current state of your mouse pointer
bool amIHovering = false;
// store the position where your mouse pointer left the widget
Offset exitFrom = Offset(0,0);
return MouseRegion(
// callback when your mouse pointer enters the underlying widget
// here you have to use 'PointerEvent'
onEnter: (PointerEvent details) => setState(() => amIHovering = true),
// callback when your mouse pointer leaves the underlying widget
onExit: (PointerEvent details) => setState(() {
amIHovering = false;
// storing the exit position
exitFrom = details.localPosition; // You can use details.position if you are interested in the global position of your pointer.
}),
// your underlying widget, can be anything
child: Container(
width: 200,
height: 200,
child: Center(
child:Text(amIHovering ? "Look mom, I'm hovering" : "I exited from: $exitFrom"),
),
),
);
}
So, in a nutshell if the target bounds lie within the coordinates x1(0), x2(10), y1(0), y2(8)因此,简而言之,如果目标边界位于坐标 x1(0)、x2(10)、y1(0)、y2(8) 内
// Sample callbackCode to check if within
// x and y are the positions returned from the gesture detector
bool isWithinTarget(x, y)
{
if (x > x1 && x < x2 && y > y1 && y < y2) {
// The pointer is within the target widget
// Perform required action
// Rebuild widget tree if necessary
return true;
}
return false;
}
The Inkwell widget can do this. Inkwell 小部件可以做到这一点。 You only need to wrap your widget around it.
您只需要将您的小部件包裹在它周围。 You can replace Gesture Detector with the Inkwell.
您可以用 Inkwell 替换 Gesture Detector。 Sample code looks like:
示例代码如下所示:
InkWell(
onHover: (value)
{
//Do something
},
onTap: ()
{
//Do something
},
child: Container(),
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.