使用GestureDetector捕捉MaterialButton子级的手势

时间:2019-05-15 17:43:00

标签: flutter gesturedetector

我想要一个MaterialButton来检测onTapDown,onTapUp和onTapCancel。

不幸的是,MaterialButtons仅检测onPressed。因此,我用GestureDetector包装了它,但是对于MaterialButtons,@Pressed是必需的,因此我将其设置为(){}。 问题是,即使我将GestureDetector行为设置为半透明,如果我点击按钮,也将仅触发Button的onPressed回调,并且会释放GestureDetector的onTapDown和onTapUp回调。我只有长按按钮才能触发onTapDown,并在释放它时触发onTapCancel。我永远无法以这种方式触发onTapUp。

我仍然希望MaterialButton具有触觉/声音/视觉反馈功能。

我试图根本不设置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绝不会向其子代传递手势。我正在接近,但我仍然不在那儿: 我发现与手势大小匹配的唯一方法是在两个容器之间“塞满女巫”,这对我来说似乎不是一个非常优雅的解决方案。顺便说一句,即使在这种情况下,我也遇到两个问题:

1:如果我(很容易)点击按钮的边框,我仍然会触发MaterialButton的onPressed而不是GestureDetector的回调。我以为它的大小为零,所以它永远都不会被窃听。如果我将GestureDetector行为设置为不透明(对我还是很奇怪),则不会显示此问题。

2:最重要:除非不小心触发了它的onPressed,否则我仍然无法获得本机的MaterialButton反馈功能。

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)
            ),
          ),
        ),
      );

1 个答案:

答案 0 :(得分:1)

您必须相反。与其将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中。

您可以通过在RaisedButton处调用onPressButton方法来轻松获得本机onTapUp的反馈功能。它将具有相同的行为。

RaisedButton(
  ...
  onPressed: onPressButton,
  child: GestureDetector(
    ...
    onTapUp: (_) {
      onPressButton();
      print('onTapUp')
    },
    ...
  ),
),