Skip to content

Instantly share code, notes, and snippets.

@eximius313
Last active January 10, 2023 16:16
Show Gist options
  • Save eximius313/71a93e260fe2e089de45d29679cd23db to your computer and use it in GitHub Desktop.
Save eximius313/71a93e260fe2e089de45d29679cd23db to your computer and use it in GitHub Desktop.
Demonstrate bug in Flutter where usage of "TransitionPage" doesn't change the page, but "MaterialPage" does
import 'package:flutter/material.dart';
void main() {
runApp(MyApp(),);
}
class MyApp extends StatelessWidget {
MyApp({super.key}) : _routerDelegate = AppRouterDelegate();
final RouterDelegate<AppState> _routerDelegate;
@override
Widget build(BuildContext context) =>
MaterialApp.router(
title: 'Test',
routerDelegate: _routerDelegate,
routeInformationParser: AppRouteInformationParser(),
backButtonDispatcher: RootBackButtonDispatcher(),
);
}
class AppRouteInformationParser extends RouteInformationParser<AppState> {
@override
Future<AppState> parseRouteInformation(RouteInformation routeInformation) {
final AppState configuration = AppState();
final uri = Uri.parse(routeInformation.location!);
if (uri.pathSegments.isEmpty) {
configuration.home = null;
} else if (uri.pathSegments.length == 1 && uri.pathSegments.first == 'true') {
configuration.home = true;
} else {
configuration.home = false;
}
return Future.value(configuration);
}
@override
RouteInformation? restoreRouteInformation(AppState configuration) =>
RouteInformation(location: configuration.home == null ? "/" : "/${configuration.home}",);
}
class AppRouterDelegate extends RouterDelegate<AppState> with ChangeNotifier, PopNavigatorRouterDelegateMixin<AppState> {
@override
final GlobalKey<NavigatorState> navigatorKey;
AppRouterDelegate() : navigatorKey = GlobalKey<NavigatorState>();
@override
Widget build(final BuildContext context) =>
Navigator(
key: navigatorKey,
pages: [
if(_configuration?.home ?? false)
TransitionPage(child: SomeScreen("Home", _configuration, key: const ValueKey('home')),)
else
//uncomment me:
//MaterialPage(child: SomeScreen("Other", _configuration, key: const ValueKey('other')),)
//comment me:
TransitionPage(child: SomeScreen("Other", _configuration, key: const ValueKey('other')),)
],
onPopPage: (route, result) {
if (!route.didPop(result)) {
return false;
}
_configuration?._home = ! (_configuration?._home ?? false);
return true;
},
);
AppState? _configuration;
@override
AppState? get currentConfiguration => _configuration;
@override
Future<void> setNewRoutePath(final AppState configuration) async {
_configuration?.removeListener(notifyListeners);
_configuration = configuration;
_configuration?.addListener(notifyListeners);
}
}
class TransitionPage extends Page {
final Widget child;
const TransitionPage({required this.child, super.key});
@override
Route createRoute(BuildContext context) {
return PageRouteBuilder(
settings: this,
pageBuilder: (context, animation, animation2) {
final tween = Tween(begin: const Offset(0.0, 1.0), end: Offset.zero);
final curveTween = CurveTween(curve: Curves.easeInOut);
return SlideTransition(
position: animation.drive(curveTween).drive(tween),
child: child,
);
},
);
}
}
class SomeScreen extends StatelessWidget {
const SomeScreen(this.text, this._appState, {super.key});
final String text;
final AppState? _appState;
@override
Widget build(BuildContext context) =>
Scaffold(
appBar: AppBar(),
body: Column(children: [
Text(text),
ElevatedButton(
onPressed: () {
_appState?.home = !(_appState?.home ?? false);
},
child: const Text("click me"))
],)
);
}
class AppState extends ChangeNotifier {
bool? _home = false;
bool? get home => _home;
set home(bool? home) {
_home = home;
notifyListeners();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment