假设我在屏幕上有3个Container
,它们通过改变颜色来做出触摸反应。当用户的手指放在他们的手指上时,它们应该改变颜色,而在触摸末端时,它们应该恢复正常。 我想要的是,即使在容器外部的屏幕上随机区域开始触摸时,这些容器也会做出反应。因此,基本上,我正在寻找的东西就像css悬停一样。
如果我分别用GestureDetector
包装每个容器,它们将不会对从其外部开始的触摸事件做出反应。关于另一个问题(很遗憾,我现在没有链接),建议用一个GestureDetector
包装所有容器,并为每个容器分配一个GlobalKey
,以使它们彼此不同。
这是检测触摸手势的面板:
class MyBoard extends StatefulWidget {
static final keys = List<GlobalKey>.generate(3,(ndx) => GlobalKey());
...
}
class _MyBoardState extends State<MyBoard> {
...
/// I control the number of buttons by the number of keys,/// since all the buttons should have a key
List<Widget> makeButtons() {
return MyBoard.keys.map((key) {
// preapre some funcitonality here
var someFunctionality;
return MyButton(key,someFunctionality);
}).toList();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (tapDownDetails) {
handleTouch(context,tapDownDetails.globalPosition);
},onTapUp: (tapUpDetails) {
finishTouch(context);
},onPanUpdate: (dragUpdateDetails) {
handleTouch(context,dragUpdateDetails.globalPosition);
},onPanEnd: (panEndDetails) {
finishTouch(context);
},onPanCancel: () {
finishTouch(context);
},child: Container(
color: Colors.green,width: 300.0,height: 600.0,child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,children: makeButtons(),),);
}
这是简单的MyButton
:
class MyButton extends StatelessWidget {
final GlobalKey key;
final Function someFunctionality;
MyButton(this.key,this.someFunctionality) : super(key: key);
@override
Widget build(BuildContext context) {
return Consumer<KeyState>(
builder: (buildContext,keyState,child) {
return Container(
width: 100.0,height: 40.0,color: keyState.touchedKey == this.key ? Colors.red : Colors.white,);
},);
}
}
在_MyBoardState
中,这就是我处理检测到哪个MyButton
被触摸的方式:
MyButton getTouchingButton(Offset globalPosition) {
MyButton currentButton;
// result is outside of [isTouchingMyButtonKey] for performance
final result = BoxHitTestResult();
bool isTouchingButtonKey(GlobalKey key) {
RenderBox renderBox = key.currentContext.findRenderObject();
Offset offset = renderBox.globalToLocal(globalPosition);
return renderBox.hitTest(result,position: offset);
}
var key = MyBoard.keys.firstWhere(isTouchingButtonKey,orElse: () => null);
if (key != null) currentButton = key.currentWidget;
return currentButton;
}
我正在使用提供程序包,而不是用MyBoard
重建整个setState
,而仅重建相关MyButton
的相关部分。仍然每个按钮都有一个侦听器,该侦听器会在每次更新时重建,并且我正在使用GlobalKey
。 On the flutter docs说:
全局密钥相对昂贵。如果您不需要上面列出的任何功能,请考虑改用Key,ValueKey,ObjectKey或UniqueKey。
但是,如果我们查看getTouchingButton
方法,则我需要GlobalKey
来获取renderBox
对象并获取currentWidget
。我还必须为每个GlobalKey
进行一次hitTest。在触发onPanUpdate
时重复此计算,这意味着用户的手指移动像素时。
UI的更新速度不够快。只需轻按一下(tapDown和tapUp以常规速度),您通常不会在MyButton
上看到任何变化。
如果需要总结我的问题,当手指以更有效,更优雅的方式悬停在不同的小部件上时,如何从不同的小部件中检测到相同的单点触摸(不抬起)?