首页 > 解决方案 > 如何将 Taps 传递给顶部小部件下方的小部件?

问题描述

我正在尝试在 Flutter 中实现一个非常简单的Card Paginator 组件(单卡)版本。

这是我创建的基本演示的示例:

class CardComponent extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        Positioned(
          top: 20.0,
          left: 20.0,
          child: 
          GestureDetector(
          // onTap should run while the text is visible on the screen
          // The text will become invisible when the Listview gest scrolled upwards
          onTap: (){print('text tapped');},
            child:
          Container(
          alignment:Alignment.topCenter,
          color: Colors.blueAccent,
        // This is fixed Text over which the card should scroll
        child: Text('Test Button')))),
        ListView(
          children: [
            //  This margin in first empty container pushes the whole card downward and makes the 'Test Button visible'
            Container(margin: EdgeInsets.only(top: 50.0)),
            // This is where the scrolling card actually starts
            Container(color: Colors.cyan[100], height: 120.0, width: 20.0),
            Container(color: Colors.cyan, height: 120.0, width: 20.0),
            Container(color: Colors.cyan[100], height: 120.0, width: 20.0),
            Container(color: Colors.cyan, height: 120.0, width: 20.0),
            Container(color: Colors.cyan[100], height: 120.0, width: 20.0),
            Container(color: Colors.cyan, height: 120.0, width: 20.0),
          ]
        )
      ],
    );
  }
}

我面临的问题是,当卡片没有向上滚动时,我无法单击按钮。固定的“测试按钮”在屏幕上可见,因为空的虚拟容器ListView向下推动可滚动。然而,由于ListView默认情况下覆盖全屏,因此onTap当按钮可见时,它永远不会在点击按钮时运行。

在此处输入图像描述

ListView如果我将/SinglleChildScrollView与类包围IgnorePointer,则整个滚动行为将停止,并且对 ListView 的子项的任何点击都会停止工作,这是不需要的。

如何在允许在 ListView 中滚动/点击时点击按钮(堆栈中的向后小部件)?或者我应该以某种不同的方式构建Card Paginator 组件吗?

标签: listviewflutterflutter-layout

解决方案


Flutter的潜在副本:如何使 ListView 对指针事件透明(但不是其非透明内容)?

您需要ListView使用GestureDetector覆盖将空容器包装在 中,onTapUp以便您可以捕获屏幕上的点击位置:

GestureDetector(
  onTapUp: (TapUpDetails tapUpDetails) {
    print("onTapUp global: " + tapUpDetails.globalPosition.toString());
  },

ListView然后,您需要通过使用该小部件的键来获取要点击的小部件的矩形:

RenderBox renderBox = _key.currentContext.findRenderObject();
Offset topLeftCorner = renderBox.localToGlobal(Offset.zero);
Size size = renderBox.size;
Rect rectangle = topLeftCorner & size;

最后,您可以计算空 Container 上的点击是否在后面的小部件的矩形内,然后调用您的代码,就好像您在GestureDetector后面的小部件上有 a 一样:

// if tap is within boundaries of the background widget
if (rectangle.contains(tapUpDetails.globalPosition)) {
  // your code here
}

推荐阅读