I have a list of pages in Navigator.pages. When I push a page with a duplicate key, I want to bring the old page on top. The problem is, the page shows without animation, it just appears on top instantly. Meanwhile the default animation works alright when pushing a new page for the first time. How do I animate the page if it is brought on top?
Here is the code:
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
final _notifier = ChangeNotifier();
final _pages = <Page>[Page1()];
class Page1 extends MaterialPage {
Page1()
: super(
key: const ValueKey('Page1'),
child: Scaffold(
appBar: AppBar(title: const Text('Page1')),
body: const Center(
child: ElevatedButton(
onPressed: _showPage2,
child: Text('Show Page2'),
),
),
),
);
}
class Page2 extends MaterialPage {
Page2()
: super(
key: const ValueKey('Page2'),
child: Scaffold(
appBar: AppBar(title: const Text('Page2')),
body: const Center(
child: ElevatedButton(
onPressed: _showPage1,
child: Text('Show Page1'),
),
),
),
);
}
void _showPage1() {
for (final page in _pages) {
if (page.key == const ValueKey('Page1')) {
_pages.remove(page);
break;
}
}
_pages.add(Page1());
_notifier.notifyListeners();
}
void _showPage2() {
for (final page in _pages) {
if (page.key == const ValueKey('Page2')) {
_pages.remove(page);
break;
}
}
_pages.add(Page2());
_notifier.notifyListeners();
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return const MaterialApp(
home: HomeScreen(),
);
}
}
class HomeScreen extends StatelessWidget {
const HomeScreen({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _notifier,
builder: (_, __) {
return Navigator(
pages: [..._pages],
transitionDelegate: const MyTransitionDelegate(),
onPopPage: (route, result) {
if (!route.didPop(result)) return false;
return true;
},
);
},
);
}
}
What I tried:
Navigator.transitionDelegateseemed like the property to handle this. But it is only invoked when a new route is pushed and not when the order is changed.To dispose the old route before bringing the page on top in hope that it will be re-created by Flutter and that could somehow trigger the animation. But I just get an exception saying the route cannot be used after disposal.
To let the navigator rebuild without the old page with
_changeNotifier.notifyListeners(); await Future.delayed(Duration.zero);before re-adding the page. But the zero duration did not work.
The workarounds so far are:
To add a non-zero duration between removing and re-adding a page. But this is noticeable.
To change the key of the new page. But I need keys to track some things in the app.
