Fix OpenContainer source(closed) widget staying hidden when the OpenContainer route is removed when the OpenContainer route is pushed from a different Route (#260)
* Fix issue where the CloseContainer widget stays hidden when the OpenContainer route is popped
diff --git a/packages/animations/lib/src/open_container.dart b/packages/animations/lib/src/open_container.dart
index 2454b3a..f9ba91a 100644
--- a/packages/animations/lib/src/open_container.dart
+++ b/packages/animations/lib/src/open_container.dart
@@ -620,16 +620,10 @@
_currentAnimationStatus = status;
switch (status) {
case AnimationStatus.dismissed:
- if (hideableKey?.currentState != null) {
- hideableKey.currentState
- ..placeholderSize = null
- ..isVisible = true;
- }
+ _toggleHideable(hide: false);
break;
case AnimationStatus.completed:
- hideableKey.currentState
- ..placeholderSize = null
- ..isVisible = false;
+ _toggleHideable(hide: true);
break;
case AnimationStatus.forward:
case AnimationStatus.reverse:
@@ -649,6 +643,25 @@
return super.didPop(result);
}
+ @override
+ void dispose() {
+ if (hideableKey?.currentState?.isVisible == false) {
+ // This route may be disposed without dismissing its animation if it is
+ // removed by the navigator.
+ SchedulerBinding.instance
+ .addPostFrameCallback((Duration d) => _toggleHideable(hide: false));
+ }
+ super.dispose();
+ }
+
+ void _toggleHideable({bool hide}) {
+ if (hideableKey?.currentState != null) {
+ hideableKey.currentState
+ ..placeholderSize = null
+ ..isVisible = !hide;
+ }
+ }
+
void _takeMeasurements({
BuildContext navigatorContext,
bool delayForSourceRoute = false,
diff --git a/packages/animations/test/open_container_test.dart b/packages/animations/test/open_container_test.dart
index 2628fbe..e276f45 100644
--- a/packages/animations/test/open_container_test.dart
+++ b/packages/animations/test/open_container_test.dart
@@ -1733,6 +1733,47 @@
expect(modalRoute.settings, routeSettings);
},
);
+
+ // Regression test for https://github.com/flutter/flutter/issues/72238.
+ testWidgets(
+ 'OpenContainer\'s source widget is visible in closed container route if '
+ 'open container route is pushed from not using the OpenContainer itself',
+ (WidgetTester tester) async {
+ final Widget openContainer = OpenContainer(
+ closedBuilder: (BuildContext context, VoidCallback action) {
+ return GestureDetector(
+ onTap: action,
+ child: const Text('Closed'),
+ );
+ },
+ openBuilder: (BuildContext context, VoidCallback action) {
+ return GestureDetector(
+ onTap: action,
+ child: const Text('Open'),
+ );
+ },
+ );
+ await tester.pumpWidget(_boilerplate(child: openContainer));
+ expect(_getOpacity(tester, 'Closed'), 1.0);
+
+ // Open the container
+ await tester.tap(find.text('Closed'));
+ await tester.pumpAndSettle();
+
+ final Element container = tester.element(
+ find.byType(OpenContainer, skipOffstage: false),
+ );
+ // Replace the open container route.
+ Navigator.pushReplacement<void, void>(container,
+ MaterialPageRoute<void>(builder: (_) => const Placeholder()));
+ await tester.pumpAndSettle();
+ // Go back to the main page and verify the closed builder is showed.
+ Navigator.pop(container);
+ await tester.pumpAndSettle();
+
+ expect(_getOpacity(tester, 'Closed'), 1.0);
+ },
+ );
}
Color _getScrimColor(WidgetTester tester) {