Skip to content

Instantly share code, notes, and snippets.

@sakiraykurt
Last active September 25, 2022 13:20
Show Gist options
  • Save sakiraykurt/1c6f7f25fda6a2ac90f14f289a131bee to your computer and use it in GitHub Desktop.
Save sakiraykurt/1c6f7f25fda6a2ac90f14f289a131bee to your computer and use it in GitHub Desktop.
Flutter animating route pages - PageSwitcherBuilder
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
static const String _title = 'Flutter Code Sample';
@override
Widget build(BuildContext context) {
return const MaterialApp(
title: _title,
home: FirstPage(),
);
}
}
class FirstPage extends StatefulWidget {
const FirstPage({Key? key}) : super(key: key);
@override
State<FirstPage> createState() => FirstPageState();
}
class FirstPageState extends State<FirstPage> {
@override
Widget build(BuildContext context) {
return PageSwitcherBuilder(
builder: (controller) {
final curved = CurvedAnimation(
parent: controller,
curve: Curves.easeOutCubic,
reverseCurve: Curves.easeInCubic);
return SlideTransition(
position:
Tween<Offset>(begin: Offset.zero, end: const Offset(-1.0, 0.0))
.animate(curved),
child: Scaffold(
backgroundColor: Colors.white,
body: Center(
child: TextButton.icon(
onPressed: () {
Navigator.of(context).push(
PageSwitcherRoute(
controller: controller,
page: SlideTransition(
position: Tween<Offset>(
begin: const Offset(1.0, 0.0),
end: Offset.zero,
).animate(curved),
child: const SecondPage(),
),
),
);
},
icon: const Icon(Icons.arrow_forward_rounded),
label: const Text(
'Go',
style: TextStyle(color: Colors.amber),
),
),
),
),
);
},
);
}
}
class SecondPage extends StatelessWidget {
const SecondPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return PageSwitcherBuilder(builder: (controller) {
final curved = CurvedAnimation(
parent: controller,
curve: Curves.linear,
reverseCurve: Curves.linear);
return ScaleTransition(
scale: Tween<double>(begin: 1.0, end: 1.3).animate(curved),
child: Scaffold(
backgroundColor: Colors.red,
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton.icon(
onPressed: () {
Navigator.of(context).pop();
},
icon: const Icon(Icons.arrow_back),
label: const Text(
'Return',
style: TextStyle(color: Colors.amber),
),
),
TextButton.icon(
onPressed: () {
Navigator.of(context).push(
PageSwitcherRoute(
controller: controller,
page: FadeTransition(
opacity: curved,
child: ScaleTransition(
scale: Tween<double>(begin: 0.95, end: 1.0)
.animate(curved),
child: const ThirdPage(),
),
),
),
);
},
icon: const Icon(Icons.arrow_forward),
label: const Text(
'Next',
style: TextStyle(color: Colors.amber),
),
),
],
),
),
),
);
});
}
}
class ThirdPage extends StatelessWidget {
const ThirdPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.purple,
body: Center(
child: TextButton.icon(
onPressed: () {
Navigator.of(context).pop();
},
icon: const Icon(Icons.arrow_back),
label: const Text(
'Return',
style: TextStyle(color: Colors.amber),
),
),
),
);
}
}
class PageSwitcherBuilder extends StatefulWidget {
const PageSwitcherBuilder(
{Key? key,
required this.builder,
this.duration = const Duration(milliseconds: 500),
this.reverseDuration = const Duration(milliseconds: 500)})
: super(key: key);
final Duration duration;
final Duration reverseDuration;
final Widget Function(AnimationController controller) builder;
@override
State<PageSwitcherBuilder> createState() => _PageSwitcherBuilderState();
}
class _PageSwitcherBuilderState extends State<PageSwitcherBuilder>
with TickerProviderStateMixin {
late final AnimationController _controller = AnimationController(
vsync: this,
duration: widget.duration,
reverseDuration: widget.reverseDuration,
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return widget.builder(_controller);
}
}
class PageSwitcherRoute extends PageRouteBuilder {
PageSwitcherRoute({
required this.controller,
required Widget page,
}) : super(pageBuilder: (BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation) {
return page;
}) {
willDisposeAnimationController = false;
}
@override
final AnimationController controller;
@override
AnimationController createAnimationController() {
return controller;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment