Repository navigation
[animations] OpenContainer should have a onOpen callback that is executed only once #74111
Description
Activity
@barangungor
can you provide yourflutter doctor -vand a complete minimal reproducible code sample (not a snippet from production)flutter doctor -v output:
flutter doctor -v
[√] Flutter (Channel beta, 1.25.0-8.2.pre, on Microsoft Windows [Version 10.0.19042.746], locale tr-TR) • Flutter version 1.25.0-8.2.pre at C:\src\flutter • Framework revision b0a2299859 (11 days ago), 2021-01-05 12:34:13 -0800 • Engine revision 92ae191c17 • Dart version 2.12.0 (build 2.12.0-133.2.beta) [!] Android toolchain - develop for Android devices (Android SDK version 30.0.2) • Android SDK at C:\Users\bbara\AppData\Local\Android\Sdk • Platform android-30, build-tools 30.0.2 • ANDROID_SDK_ROOT = C:\Users\bbara\AppData\Local\Android\Sdk • Java binary at: C:\Program Files\Android\Android Studio\jre\bin\java • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01) X Android license status unknown. Run `flutter doctor --android-licenses` to accept the SDK licenses. See https://flutter.dev/docs/get-started/install/windows#android-setup for more details. [√] Android Studio (version 4.1.0) • Android Studio at C:\Program Files\Android\Android Studio • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 1.8.0_242-release-1644-b01) [!] Connected device ! No devices available ! Doctor found issues in 2 categories.And this is my OpenContainer Code :
Code
OpenContainer( transitionDuration: Duration(milliseconds: 300), closedBuilder: (BuildContext c, VoidCallback action) { return Container( margin: EdgeInsets.only( top: MediaQuery.of(context) .size .height / 150, ), child: Image.network( IMAGE_ORIGINAL + _userRepo .campaignObject .values .elementAt(campaignCatIndex)[ 'campaigns'][ campaignIndex] ['image'] .toString())); }, openBuilder: (BuildContext c, VoidCallback action) { _supRepo.getProductStore(context, _userRepo.activePage['id'], campaign: _userRepo .campaignObject.values .elementAt( campaignCatIndex)[ 'campaigns'] [campaignIndex]['id']); return ProductPage( showAppBar: true, ); }, tappable: true, );
[...] and a complete minimal reproducible code sample (not a snippet from production)
OpenContainer( transitionDuration: Duration(milliseconds: 300), closedBuilder: (BuildContext c, VoidCallback action) { return Container( margin: EdgeInsets.only( top: MediaQuery.of(context) .size .height / 150, ), child: Image.network( IMAGE_ORIGINAL + _userRepo .campaignObject .values .elementAt(campaignCatIndex)[ 'campaigns'][ campaignIndex] ['image'] .toString())); }, openBuilder: (BuildContext c, VoidCallback action) { _supRepo.getProductStore(context, _userRepo.activePage['id'], campaign: _userRepo .campaignObject.values .elementAt( campaignCatIndex)[ 'campaigns'] [campaignIndex]['id']); return ProductPage( showAppBar: true, ); }, tappable: true, );
@barangungor
this seems a snippet from production code rather than aminimal reproducible code sample
in this link you can find a reference to what this definition implies@iapicca
I had to do this to explain my problem. I think it's pretty understandable. I want to run a function only once when it is opened. Instead of the code before "return" in the code block I provided, print ('TEST'); you can write and try. When opening my page, the function works 2 or 3 times and I don't want that to happen.Considering this as a proposal based on the use-case. I suggest to add an
onOpencallback (similar toonClosed) which should be called only once: when the container is being opened.Thank you
- changed the title
[-]OpenContainer onOpened function?[/-][+][animations] OpenContainer should have a onOpen callback that is executed only once[/+]on Jan 18, 2021 - addedp: animationsThe animations packageThe animations packagec: proposalA detailed proposal for a change to FlutterA detailed proposal for a change to Flutter
on Jan 18, 2021 barangungor commented
on Jan 18, 2021 on Jan 18, 2021 · Hidden as off-topicAuthorshow commentMore actionspedromassangocode commented
on Jan 18, 2021 on Jan 18, 2021 · Hidden as off-topicshow commentMore actionsHey @pedromassangocode can I create a pr for this?
Hey @pedromassangocode can I create a pr for this?
Yes you can.
11 remaining items
In case someone still needs a solution. Here is my work around.
return OpenContainer( tappable: false, transitionDuration: Duration(milliseconds: 700), closedBuilder: (context, openContainer) { return GestureDetector( onTap: () { // Your onOpen codes openContainer(); //this function triggers and executes the openBuilder property }, child: Container( padding: const EdgeInsets.all(10), color: Colors.blue, child: Text('Open Container'), ), ); }, openBuilder: (context, closeContainer) { return Container( color: Colors.red, ); }, );This feature really is a must have. +1 from me and I'll be sure to follow whatever news in this thread.
I also need this, openBuilder returns a page but before the return, I'm logging with firebase analytics. That logging call gets triggered 5-10 times on every opening.
You can use the workaround proposed in the comment above: #74111 (comment)
I have been struggling with poor animation performance and also other strange behavior in my app until I noticed that the
openBuildergets called multiple times. All the issues I had were caused by this. The widget I build inopenBuilderis a very complex page so it definitely must not be created multiple times. This was quite unexpected behavior and unfortunately the suggested workaround does not help in my case for some reason. TheopenBuildergets still called twice.So I implemented another workaround which is to save the widget created in
openBuilderand in subsequent calls return the saved widget. One challenge is that where to reset the saved instance (you can't do it incloseBuilderas it also gets called "randomly" multiple times). Here is a simplified sample of my solution if it helps anyone:class AddEventFloatingActionButton extends StatefulWidget { const AddEventFloatingActionButton({super.key}); @override State<AddEventFloatingActionButton> createState() => _AddEventFloatingActionButtonState(); } class _AddEventFloatingActionButtonState extends State<AddEventFloatingActionButton> { Widget? _openBuilderWidget; final _isMenuOpen = ValueNotifier<bool>(false); @override Widget build(BuildContext context) { return SpeedDial( onOpen: () => _openBuilderWidget = null, isOpenOnStart: _isMenuOpen.value, openCloseDial: _isMenuOpen, children: <AddEventCommand>[ AddEventCommand(EventTypes.a), ... ].map( (c) { return SpeedDialChild( child: OpenContainer( openBuilder: (BuildContext context, VoidCallback _) { scheduleMicrotask(() { _isMenuOpen.value = false; }); if (_openBuilderWidget != null) { return _openBuilderWidget!; } _openBuilderWidget = EditEventPage(newEventType: c.eventType); return _openBuilderWidget!; }, closedBuilder: (context, openContainer) { return Container(...); }, ), ); }, ).toList(), ); } }
- addedteam-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem team
on Jul 8, 2023 - marked When using OpenContainer I am seeing openBuilder being called numerous times (60). #162564 as a duplicate of this issue
on Feb 3, 2025 - addedteam-designOwned by Design Languages teamOwned by Design Languages teamtriaged-designTriaged by Design Languages teamTriaged by Design Languages teamand removedteam-ecosystemOwned by Ecosystem teamOwned by Ecosystem teamtriaged-ecosystemTriaged by Ecosystem teamTriaged by Ecosystem team
on Aug 26, 2026
I'm using openContainer in my app. I want call a function on OpenContainer's openBuilder page opened.
My Code Like this but the function runs 2-3 times onOpen and onClose. I want call only 1 time after page opened: