How to pass Taps to widgets below the top widget?

廉价感情. 提交于 2020-06-12 07:03:15

问题


I'm trying to implement a very simple version of Card Paginator Component (single card) in Flutter.

Here is an example of a basic demo I've created:

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

The issue I'm facing is, I'm unable to click the button when the card in not scrolled up. The fixed 'Test Button' is visible on the screen because of the empty dummy Container pushing the scrollable ListView downwards. Yet, since the ListView covers the full screen by default, hence the onTap never runs on tapping the button when it's visible.

If I surround the ListView/SinglleChildScrollView with IgnorePointer class, the whole scrolling behaviour stops and also any taps to the children of the ListView stops working which is not desired.

How to tap on the button (backward widget in Stack) while allowing scrolling/tapping in ListView? Or should I approach building Card Paginator Component is some different way?


回答1:


I don't know if you want the fix bar height with button as per your current code but I can help you with the design as per your shared Card Paginator Component.

For that you can use CustomScrollView with SliverAppBar.

Here is the code

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

Hope this helps...




回答2:


Potential duplicate of Flutter: How to make a ListView transparent to pointer events (but not its non-transparent contents)?

You need to wrap your empty Container within the ListView with a GestureDetector overriding onTapUp so that you can capture the tap position on the screen:

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

You then need to get the rectangle of the widget behind the ListView that you want to tap on, by using that widget's key:

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

And finally you can calculate whether the tap on the empty Container is within the rectangle of the widget behind, and at that point invoke your code as if you had a GestureDetector on the widget behind:

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


来源:https://stackoverflow.com/questions/57929582/how-to-pass-taps-to-widgets-below-the-top-widget

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!