Reputation: 1027
Working code here:
OpenContainer(
openBuilder: (context, action) => const SelectedProduct(),
closedBuilder: (context, action) => Card(),
),
/*Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
context.read<DownloadImages>().currentProduct = i;
context.read<DownloadImages>().notifyListeners();
//Navigator.pushNamed(context, '/seven');
},
splashColor: Colors.transparent,
)
),
),*/
The commented out code is what I want to achieve. Ignore the other variables I set in onTap
, that is not my focus, but my focus is to show this InkWell
ripple when I click on the Card
, or while holding it in place, and only then start the openBuilder
.
What happens is when the InkWell
is in place, the InkWell
overtakes the OpenContainer
builders and only its onTap
gets used. How do I ignore InkWell's onTap
for instance, and only get its animation to work along with OpenContainer
?
Note: Both of these are within a Stack
widget.
Complete code for testing:
import 'package:flutter/material.dart'
import 'package:animations/animations.dart';
class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'TestPage',
home: const Products(),
);
}
}
class Products extends StatefulWidget {
const Products({Key? key}) : super(key: key);
@override
State<Products> createState() => _ProductsState();
}
class _ProductsState extends State<Products> {
@override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
return Future.value(false);
},
child: Scaffold(
body: Container(
alignment: Alignment.center,
child: SingleChildScrollView(
padding:
const EdgeInsets.only(top: 20, bottom: 20, left: 15, right: 15),
child: Column(
children: [
Stack(
children: [
OpenContainer(
openBuilder: (context, action) => const SelectedProduct(),
closedBuilder: (context, action) => Card(
child: Text('Test Card')
),
),
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
//Navigator.pushNamed(context, '/seven');
},
splashColor: Colors.transparent,
)
),
),
],
),
const SizedBox(height: 10),
],
)
),
),
),
);
}
}
Upvotes: 0
Views: 854
Reputation: 887
Easy! Wrap the closedBuilder
widget with InkWell and use the builder's action
parameter as the onTap
function to manually triggers the container open. Also, sets the tappable
parameter to false.
Example code:
OpenContainer(
tappable: false,
openBuilder: (context, action) {
return const Widget2();
},
closedBuilder: (context, action) {
return InkWell(
onTap: action, // this will open the container
child: Widget1(),
);
},
);
Demo video:
Upvotes: 0
Reputation: 63604
The widget priority, bottom to top for tap event. Place tappable widget at bottom and background widgets at top.
If you swap the location, it will work.
Stack(
children: [
Positioned.fill(
child: Material(
color: Colors.transparent,
child: InkWell(
onTap: () {
//Navigator.pushNamed(context, '/seven');
},
splashColor: Colors.transparent,
),
),
),
OpenContainer(
tappable: true,
openBuilder: (context, action) => Container(
color: Colors.green,
height: 200,
width: 200,
),
closedBuilder: (context, action) => Card(
child: Text('Test Card'),
),
),
],
),
Stack
Material(
color: Colors.green,
child: Ink(
width: 200,
height: 200,
child: InkWell(
onTap: () {},
child: Center(
child: OpenContainer(
// closedColor: Colors.pink, or card color
openBuilder: (context, action) =>
const Text("Open card"),
closedBuilder: (context, action) =>
Card(child: Text('Test Card')),
// ),
),
),
),
))
Upvotes: 1