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?
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
}
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With