explicit · difficulty 2/5 · verified Flutter 3.32 / 2026-06
Use PageRouteBuilder to customize the enter animation (fade + a slight slide-up) instead of the default platform transition.
// ✅ Recommended: PageRouteBuilder + CurvedAnimation, fade-in + slide-up, with explicit enter/exit durations.
// Paste straight into DartPad (https://dartpad.dev) to run.
import 'package:flutter/material.dart';
void main() => runApp(const _App());
class _App extends StatelessWidget {
const _App();
@override
Widget build(BuildContext context) =>
const MaterialApp(debugShowCheckedModeBanner: false, home: _HomePage());
}
// Reusable transition: fade-in + a slight slide-up
Route<T> fadeSlideRoute<T>(Widget page) {
return PageRouteBuilder<T>(
transitionDuration: const Duration(milliseconds: 350),
reverseTransitionDuration: const Duration(milliseconds: 300),
pageBuilder: (context, animation, secondaryAnimation) => page,
transitionsBuilder: (context, animation, secondaryAnimation, child) {
final curved = CurvedAnimation(
parent: animation,
curve: Curves.easeOutCubic,
);
return FadeTransition(
opacity: curved,
child: SlideTransition(
position: Tween<Offset>(
begin: const Offset(0, 0.08),
end: Offset.zero,
).animate(curved),
child: child, // reuse the passed-in child
),
);
},
);
}
class _HomePage extends StatelessWidget {
const _HomePage();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Home')),
body: Center(
child: FilledButton(
onPressed: () =>
Navigator.of(context).push(fadeSlideRoute(const _SecondPage())),
child: const Text('Open with fade + slide'),
),
),
);
}
}
class _SecondPage extends StatelessWidget {
const _SecondPage();
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Second')),
body: const Center(child: Text('Hello 👋')),
);
}
}