Last active
December 31, 2022 11:34
-
-
Save davidhicks980/57e57e674293dd72bca1340e9e8ebac6 to your computer and use it in GitHub Desktop.
Flutter: Listen to page transition status
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/cupertino.dart'; | |
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(const PageTransitionDemo()); | |
} | |
/// Demonstrates how to show a widget after a page is finished transitioning | |
class PageTransitionDemo extends StatelessWidget { | |
const PageTransitionDemo({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
title: 'Flutter Demo', | |
initialRoute: "/", | |
routes: { | |
"/": (context) => const Origin(), | |
}, | |
); | |
} | |
} | |
/// Sample Origin page -- does not contain any relevant logic | |
class Origin extends StatelessWidget { | |
const Origin({super.key}); | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text("Origin"), | |
), | |
body: Center( | |
child: TextButton( | |
onPressed: () { | |
Navigator.push( | |
context, | |
PageRouteBuilder( | |
transitionDuration: const Duration(milliseconds: 5000), | |
pageBuilder: (BuildContext context, Animation<double> animation, | |
Animation<double> secondaryAnimation) { | |
return CupertinoPageTransition( | |
primaryRouteAnimation: animation, | |
secondaryRouteAnimation: secondaryAnimation, | |
linearTransition: false, | |
child: const Destination(), | |
); | |
}, | |
), | |
); | |
}, | |
child: const Text("Go to destination"), | |
), | |
), | |
); | |
} | |
} | |
class Destination extends StatefulWidget { | |
const Destination({super.key}); | |
@override | |
State<Destination> createState() => _DestinationState(); | |
} | |
class _DestinationState extends State<Destination> { | |
bool isWidgetVisible = false; | |
Animation<double>? get transitionIn => ModalRoute.of(context)?.animation; | |
@override | |
void initState() { | |
super.initState(); | |
/// Add post frame callback so that we can access BuildContext | |
WidgetsBinding.instance.addPostFrameCallback((timeStamp) { | |
///Listen for page animation status changes | |
transitionIn?.addStatusListener(_handleCompletedPageTransition); | |
}); | |
} | |
/// Unsubscribes animation status listener and toggles isWidgetVisible | |
/// once our forward animation completes | |
void _handleCompletedPageTransition(AnimationStatus status) { | |
if (status == AnimationStatus.completed) { | |
transitionIn?.removeStatusListener(_handleCompletedPageTransition); | |
setState(() { | |
isWidgetVisible = true; | |
}); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
appBar: AppBar( | |
title: const Text("Destination"), | |
backgroundColor: Colors.black, | |
), | |
body: Center( | |
child: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
children: <Widget>[ | |
if (isWidgetVisible) | |
const Center( | |
child: Text( | |
'Animation completed', | |
style: TextStyle(fontSize: 32), | |
), | |
) | |
else | |
AnimatedBuilder( | |
animation: transitionIn!, | |
builder: ((context, child) { | |
return Column( | |
children: [ | |
CircularProgressIndicator( | |
value: transitionIn!.value, | |
color: Color.lerp( | |
Colors.blue, | |
Colors.green, | |
transitionIn!.value, | |
), | |
), | |
const SizedBox(height: 20), | |
Text( | |
"Transition Progress ${transitionIn!.value.toStringAsPrecision(3)}", | |
style: const TextStyle(fontSize: 20), | |
), | |
], | |
); | |
}), | |
), | |
], | |
), | |
), | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment