【问题标题】:How to delegate ontap event in flutter to bottom widget in stack?如何将颤动中的 ontap 事件委托给堆栈中的底部小部件?
【发布时间】:2020-07-02 18:35:20
【问题描述】:

如果两个容器在堆栈中完全重叠,那么当点击顶部的小部件时,我们如何检测底部的onTap() 事件?

用例:

我的顶部容器是透明的。我正在使用这个透明的容器水龙头为顶部小部件设置动画(这个顶部小部件粘在屏幕底部)。在点击时,我想在位置为相同的底部元素设置动画。

另外,我实现了自定义 Rawgesture,但我没有看到手势领域冲突。仅当元素的位置使得一个是父级而第二个是子级时,才会检测到这种竞技场冲突。

import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Stack(children: <Widget>[
        GestureDetector(
          onTap: () {
            print('green clicked.');
          },
          child: Container(
            color: Colors.green,
            width: 400,
            height: 400,
          ),
        ),
        GestureDetector(
          onTap: () {
            print('red clicked.');
          },
          child: Container(
            color: Colors.red,
            width: 200,
            height: 200,
          ),
        ),
      ]),
    );
  }
}

在上面的示例中,当我单击红色容器时,它将打印red clicked,但也存在绿色容器的某些部分。我想知道这两个事件是否都可以调用?

谢谢。

【问题讨论】:

  • 尝试更改顶部小部件的 hitTestBehavior
  • @Pavel 那是我做的第一件事。但是没有用。
  • 如果要按下底部容器项,则必须将上部容器颜色设置为透明。有时取决于,例如上部容器包含文本,而下部容器包含一些图像,而不是您只能在文本字体区域上按下文本(如果有任何事件),除此之外,您可以获得下部图像的事件如果您保持文本的背景颜色透明,则事件。
  • @SanketVekariya 我的顶部容器是透明的。我正在使用这个透明的容器水龙头来为顶部小部件设置动画。同样在点击时,我想为相同的底部元素设置动画。我还实现了自定义 Rawgesture,但我没有看到手势竞技场冲突,所以无法弄清楚发生了什么。我已经做了解决方法,但想知道它是否可能。
  • 您能与我们分享一个“可运行代码”示例吗?了解更多关于 的信息,以便我们提供帮助

标签: flutter flutter-layout


【解决方案1】:

AFAIK,没有直接的方法可以知道用户是否点击了底层小部件。但是,我运行了您的红色和绿色容器代码,并通过 onTapDown 事件实现了它

最简单的解决方案(没有 onTapDown)::

增加了以下功能:

void onGreenClick()
  {
    print("Green clicked");
  }

将 Green 的 onTap 处理程序更改为:

onTap: onGreenClick,

并在 Red 的 onTap 中添加 onGreenClick() 为:

onTap: () {
            print('red clicked.');
            onGreenClick();
          },

但是,正如您猜测的那样,这仅在小部件彼此完全重叠时才有效。如果有一些区域存在红色容器但不是绿色的,那么上面的容器就会失败。要实现这一点,您可以使用onTapDown,如下所示:

将 onTapDown 处理程序添加到红色和绿色(在 GestureDetector 下)为:

onTapDown: (TapDownDetails details) => onTapDown(context, details),

处理函数在哪里:

void onTapDown(BuildContext context, TapDownDetails details) {
    print('${details.globalPosition}');
    final RenderBox box = context.findRenderObject();
    final Offset localOffset = box.globalToLocal(details.globalPosition);
    setState(() {
      posx = localOffset.dx;
      posy = localOffset.dy;
    });
    if (posx < 100.0 && posy < 100.0) onGreenClick();
  }

现在,如果您看到最后一行,我们只在特定的 x,y 坐标上调用 onGreenClick。

因此,即使点击红色,您也会在调试输出窗口中获得“绿色点击”。

完整代码可here

【讨论】:

  • 我尝试了这个解决方法。这是tapDown 的问题,我必须用tapDown 做很多圈才能确定它是否只是tapdown 或拖动以及任何其他可以触发tapDown 的事件。如果你长按,那么它仍然是tapdown,依此类推……
  • 在我的应用程序中,绿色和红色容器有 Twins 所以红色水龙头都需要动画。此外,我还有其他手势,例如长按、双击、滑动,我也使用 tapdown 进行边缘点击等等......如果你知道任何简单的方法来实现所有这些,那也会有很大帮助。跨度>
  • 我想我明白了,除了 - 如果在红色水龙头上都需要动画,那么你不需要 onTapDown;你为什么不简单地从onRedClicked() 调用onGreenClicked()(上面提到的'最简单的解决方案'?
  • 是的。这是目前的做法。我有共享类,所有事件都被重定向并进行调用。我只是想知道是否有另一种方法可以做到这一点。我有很多做类似事情的小部件。
  • 我从昨天开始就考虑了。在我看来,这种(当前/已回答)方法更好。因为 A. 这很简单。 B. 灵活且易于维护,更重要的是 C. 您将始终处于完全控制之中 D. 未来证明,即如果明天需求发生变化,例如在所有情况下都不要调用 onGreenClicked,那么将很容易采纳。 ....只是我的两分钱。 :-)
猜你喜欢
  • 2021-11-30
  • 2019-07-29
  • 2021-02-21
  • 1970-01-01
  • 2021-09-09
  • 2021-09-25
  • 1970-01-01
  • 2012-06-05
  • 1970-01-01
相关资源
最近更新 更多