如何将Taps传递到顶部小部件下方的小部件?

时间:2019-09-13 19:48:42

标签: listview flutter flutter-layout

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

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

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永远不会在可见时轻按按钮。

enter image description here

如果我将ListView / SinglleChildScrollViewIgnorePointer类包围起来,则整个滚动行为将停止,并且对ListView子级的任何轻击也将停止,这是不希望的。

如何在允许在ListView中滚动/点击的同时点击按钮(Stack中的向后小部件)?还是应该以其他方式构建Card Paginator Component

2 个答案:

答案 0 :(得分:2)

我不知道您是否要根据当前代码使用按钮来固定固定高度,但是我可以根据您共享的Card Paginator Component来帮助您进行设计。

为此,您可以将CustomScrollViewSliverAppBar一起使用。

这是代码

   CustomScrollView(
      slivers: <Widget>[
        SliverAppBar(
          backgroundColor: Colors.white,
          expandedHeight: 200,
          centerTitle: true,
          pinned: true,
          elevation: 0,
          flexibleSpace: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Expanded(
                child: Center(
                  child: Container(
                      padding: const EdgeInsets.all(10.0),
                      child: CircleAvatar(
                        backgroundColor: Colors.grey.shade400,
                        child: Image.asset("assets/user.png"),
                        maxRadius: 80,
                      )),
                ),
              ),
            ],
          ),
        ),
        SliverToBoxAdapter(
          child: Padding(
            padding: const EdgeInsets.all(8.0),
            child: Center(child: Text("Aakash Kumar", style: Theme.of(context).textTheme.headline,)),
          ),
        ),
        SliverFixedExtentList(
          itemExtent: 150.0,
          delegate: SliverChildListDelegate(
            [
              Container(color: Colors.red),
              Container(color: Colors.purple),
              Container(color: Colors.green),
              Container(color: Colors.orange),
              Container(color: Colors.yellow),
              Container(color: Colors.pink),
            ],
          ),
        ),
      ],
    );

希望这对您有帮助...

答案 1 :(得分:1)

Flutter: How to make a ListView transparent to pointer events (but not its non-transparent contents)?的可能重复项

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

onTapUp

然后,您需要通过使用小部件的键来获取要点击的GestureDetector( onTapUp: (TapUpDetails tapUpDetails) { print("onTapUp global: " + tapUpDetails.globalPosition.toString()); }, 后面的小部件的矩形:

ListView

最后,您可以计算出在空Container上的点击是否在后面的小部件的矩形内,然后调用您的代码,就像在后面的小部件上有RenderBox renderBox = _key.currentContext.findRenderObject(); Offset topLeftCorner = renderBox.localToGlobal(Offset.zero); Size size = renderBox.size; Rect rectangle = topLeftCorner & size; 一样:

GestureDetector