From b0af30af72a090951bee19ee80f6f53831fed0a0 Mon Sep 17 00:00:00 2001 From: chunhtai <47866232+chunhtai@users.noreply.github.com> Date: Wed, 30 Dec 2020 17:56:39 -0800 Subject: [PATCH] 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 --- .../animations/lib/src/open_container.dart | 29 +++++++++---- .../animations/test/open_container_test.dart | 41 +++++++++++++++++++ 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/packages/animations/lib/src/open_container.dart b/packages/animations/lib/src/open_container.dart index 2454b3aeb5..f9ba91ad41 100644 --- a/packages/animations/lib/src/open_container.dart +++ b/packages/animations/lib/src/open_container.dart @@ -620,16 +620,10 @@ class _OpenContainerRoute extends ModalRoute { _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 @@ class _OpenContainerRoute extends ModalRoute { 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 2628fbef9f..e276f45794 100644 --- a/packages/animations/test/open_container_test.dart +++ b/packages/animations/test/open_container_test.dart @@ -1733,6 +1733,47 @@ void main() { 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(container, + MaterialPageRoute(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) {