使用 GestureDetector 捕捉 MaterialButton 的手势 child
Using GestureDetector to catch gestures of MaterialButton child
我想要一个 MaterialButton 来检测 onTapDown、onTapUp 和 onTapCancel。
不幸的是 MaterialButtons 只检测 onPressed。所以我用 GestureDetector 包裹它,但对于 MaterialButtons,onPressed 是 @required 所以我将它设置为 () {}。
问题是,即使我将 GestureDetector 行为设置为半透明,如果我点击按钮,只会触发 Button 的 onPressed 回调,并且我会松开 GestureDetector 的 onTapDown 和 onTapUp 回调。如果我长按按钮,我只会触发 onTapDown,当我松开按钮时,会触发 onTapCancel。我永远无法以这种方式触发 onTapUp。
我仍然想要 MaterialButton,因为它具有 haptic/sound/visual 反馈功能。
我尝试根本不在 MaterialButton 上设置 onPressed,(奇怪的是)它仍然有效,但按钮被禁用并且根本没有给出任何反馈。
GestureDetector(
behavior: HitTestBehavior.translucent,
onTapDown: (_) {
th.handleTap(i, 0);
},
onTapUp: (_) {
th.handleTap(i, 1);
},
onTapCancel: () {
th.handleTap(i, 2);
},
child: MaterialButton(
onPressed: () {},
child: Container(
margin: EdgeInsets.all(5),
child: Icon(icon),
),
)
)
编辑:
谢谢 Hugo Passos,出于某种原因,我认为 MaterialButtons 永远不会将手势传递给它们的 children。我越来越近了,但我仍然不在那里:
我发现匹配手势大小的唯一方法是在两个容器之间 "sandwitch" 它,这对我来说看起来不是一个非常优雅的解决方案。顺便说一句,即使在这种情况下我 运行 陷入两个问题:
1:如果我(很容易地)点击按钮的边框,我仍然会触发 MaterialButton 的 onPressed 而不是 GestureDetector 的回调。我认为它的大小为零,所以它永远不会被点击。如果我将 GestureDetector 行为设置为不透明,则不会显示此问题(对我来说仍然很奇怪)。
2: 最重要: 我仍然无法获得原生的 MaterialButton 反馈功能,除非我不小心触发了它的 onPressed。
Container(
margin: EdgeInsets.all(2),
width: buttonSize,
height: buttonSize,
child: RaisedButton(
padding: EdgeInsets.zero,
onPressed: () {print("onTap");},
child: Container(
margin: EdgeInsets.zero,
width: buttonSize,
height: buttonSize,
child: GestureDetector(
onTapDown: (_) {
th.handleTap(i, 0);
},
onTapUp: (_) {
th.handleTap(i, 1);
},
onTapCancel: () {
th.handleTap(i, 2);
},
child: Icon(icon)
),
),
),
);
你必须反其道而行之。不要将 RaisedButton
包装在 GestureDetector
中,而是将 GestureDetector
包装在 RaisedButton
中。您还必须删除 RaisedButton
填充,以便扩展 GestureDetector
作用区域。
RaisedButton(
padding: EdgeInsets.zero,
onPressed: () {},
child: Container(
height: 40,
width: 80,
child: GestureDetector(
onTapDown: (_) => print('onTapDown'),
onTapUp: (_) => print('onTapUp'),
onTapCancel: () => print('onTapCancel'),
child: Icon(icon),
),
),
),
编辑
Center(
child: RaisedButton(
padding: EdgeInsets.zero,
onPressed: () => print('onPressed'),
child: GestureDetector(
onTapDown: (_) => print('onTapDown'),
onTapUp: (_) => print('onTapUp'),
onTapCancel: () => print('onTapCancel'),
child: Container(
color: Colors.blue,
height: 40,
width: 80,
child: Icon(icon),
),
),
),
);
不过,您会得到一个调用 onPressed
的小边框。如果这让您感到困扰,请将此代码包装在另一个 Container
中,就像您在代码中所做的那样。
您可以通过在 onTapUp
调用 onPressButton
方法轻松获得本机 RaisedButton
反馈功能。它将具有相同的行为。
RaisedButton(
...
onPressed: onPressButton,
child: GestureDetector(
...
onTapUp: (_) {
onPressButton();
print('onTapUp')
},
...
),
),
我想要一个 MaterialButton 来检测 onTapDown、onTapUp 和 onTapCancel。
不幸的是 MaterialButtons 只检测 onPressed。所以我用 GestureDetector 包裹它,但对于 MaterialButtons,onPressed 是 @required 所以我将它设置为 () {}。 问题是,即使我将 GestureDetector 行为设置为半透明,如果我点击按钮,只会触发 Button 的 onPressed 回调,并且我会松开 GestureDetector 的 onTapDown 和 onTapUp 回调。如果我长按按钮,我只会触发 onTapDown,当我松开按钮时,会触发 onTapCancel。我永远无法以这种方式触发 onTapUp。
我仍然想要 MaterialButton,因为它具有 haptic/sound/visual 反馈功能。
我尝试根本不在 MaterialButton 上设置 onPressed,(奇怪的是)它仍然有效,但按钮被禁用并且根本没有给出任何反馈。
GestureDetector(
behavior: HitTestBehavior.translucent,
onTapDown: (_) {
th.handleTap(i, 0);
},
onTapUp: (_) {
th.handleTap(i, 1);
},
onTapCancel: () {
th.handleTap(i, 2);
},
child: MaterialButton(
onPressed: () {},
child: Container(
margin: EdgeInsets.all(5),
child: Icon(icon),
),
)
)
编辑: 谢谢 Hugo Passos,出于某种原因,我认为 MaterialButtons 永远不会将手势传递给它们的 children。我越来越近了,但我仍然不在那里: 我发现匹配手势大小的唯一方法是在两个容器之间 "sandwitch" 它,这对我来说看起来不是一个非常优雅的解决方案。顺便说一句,即使在这种情况下我 运行 陷入两个问题:
1:如果我(很容易地)点击按钮的边框,我仍然会触发 MaterialButton 的 onPressed 而不是 GestureDetector 的回调。我认为它的大小为零,所以它永远不会被点击。如果我将 GestureDetector 行为设置为不透明,则不会显示此问题(对我来说仍然很奇怪)。
2: 最重要: 我仍然无法获得原生的 MaterialButton 反馈功能,除非我不小心触发了它的 onPressed。
Container(
margin: EdgeInsets.all(2),
width: buttonSize,
height: buttonSize,
child: RaisedButton(
padding: EdgeInsets.zero,
onPressed: () {print("onTap");},
child: Container(
margin: EdgeInsets.zero,
width: buttonSize,
height: buttonSize,
child: GestureDetector(
onTapDown: (_) {
th.handleTap(i, 0);
},
onTapUp: (_) {
th.handleTap(i, 1);
},
onTapCancel: () {
th.handleTap(i, 2);
},
child: Icon(icon)
),
),
),
);
你必须反其道而行之。不要将 RaisedButton
包装在 GestureDetector
中,而是将 GestureDetector
包装在 RaisedButton
中。您还必须删除 RaisedButton
填充,以便扩展 GestureDetector
作用区域。
RaisedButton(
padding: EdgeInsets.zero,
onPressed: () {},
child: Container(
height: 40,
width: 80,
child: GestureDetector(
onTapDown: (_) => print('onTapDown'),
onTapUp: (_) => print('onTapUp'),
onTapCancel: () => print('onTapCancel'),
child: Icon(icon),
),
),
),
编辑
Center(
child: RaisedButton(
padding: EdgeInsets.zero,
onPressed: () => print('onPressed'),
child: GestureDetector(
onTapDown: (_) => print('onTapDown'),
onTapUp: (_) => print('onTapUp'),
onTapCancel: () => print('onTapCancel'),
child: Container(
color: Colors.blue,
height: 40,
width: 80,
child: Icon(icon),
),
),
),
);
不过,您会得到一个调用 onPressed
的小边框。如果这让您感到困扰,请将此代码包装在另一个 Container
中,就像您在代码中所做的那样。
您可以通过在 onTapUp
调用 onPressButton
方法轻松获得本机 RaisedButton
反馈功能。它将具有相同的行为。
RaisedButton(
...
onPressed: onPressButton,
child: GestureDetector(
...
onTapUp: (_) {
onPressButton();
print('onTapUp')
},
...
),
),