Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass Taps to widgets below the top widget?

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.

enter image description here

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?

like image 638
Mayur Dhurpate Avatar asked Sep 13 '19 19:09

Mayur Dhurpate


2 Answers

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
}
like image 62
Ovidiu Avatar answered Sep 20 '22 00:09

Ovidiu


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...

like image 20
Aakash Kumar Avatar answered Sep 20 '22 00:09

Aakash Kumar