Flutter offers a rich set of pre-defined route transitions, but sometimes you need something unique to match your app’s design language. Fortunately, Flutter provides the PageRouteBuilder class, allowing you to create custom transitions that can greatly enhance the user experience.
Understanding PageRouteBuilder
PageRouteBuilder is a class in Flutter that enables you to define custom page routes and transitions. Unlike the default MaterialPageRoute, which provides standard platform-specific transitions, PageRouteBuilder gives you complete control over how your pages animate in and out.
Why Use Custom Transitions?
- Branding: Maintain a consistent visual identity with unique transitions.
- User Experience: Create memorable and engaging interactions.
- Differentiation: Stand out from the crowd with innovative animations.
Implementing Custom Transitions with PageRouteBuilder
To create custom transitions using PageRouteBuilder, follow these steps:
Step 1: Create a Custom Route
First, create a custom route using PageRouteBuilder. Define the pageBuilder, transitionsBuilder, and other properties as needed.
import 'package:flutter/material.dart';
class CustomPageRoute extends PageRouteBuilder {
final Widget child;
final AxisDirection direction;
CustomPageRoute({
required this.child,
this.direction = AxisDirection.right, // Default slide from right
}) : super(
transitionDuration: const Duration(milliseconds: 500), // Adjust as needed
reverseTransitionDuration: const Duration(milliseconds: 500),
pageBuilder: (context, animation, secondaryAnimation) => child,
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
SlideTransition(
position: Tween(
begin: getBeginOffset(direction),
end: Offset.zero,
).animate(animation),
child: child,
),
);
static Offset getBeginOffset(AxisDirection direction) {
switch (direction) {
case AxisDirection.up:
return const Offset(0, 1);
case AxisDirection.down:
return const Offset(0, -1);
case AxisDirection.left:
return const Offset(1, 0);
case AxisDirection.right:
return const Offset(-1, 0);
}
}
}
Key components in this example:
pageBuilder: Builds the content of the route, returning thechildwidget.transitionsBuilder: Defines the transition animation usingSlideTransition. You could also useFadeTransition,ScaleTransition,RotationTransition, or any combination of animated widgets.transitionDurationandreverseTransitionDuration: Control the length of the transition animations.
Step 2: Define the Transition Animation
In the transitionsBuilder, specify the animation for the transition. Common animations include:
- Slide Transition: Slides the new page into view.
- Fade Transition: Fades the new page in.
- Scale Transition: Scales the new page from a point.
- Rotation Transition: Rotates the new page into view.
Here’s how you can create a Slide Transition:
import 'package:flutter/material.dart';
class CustomPageRoute extends PageRouteBuilder {
final Widget child;
final AxisDirection direction;
CustomPageRoute({
required this.child,
this.direction = AxisDirection.right, // Default slide from right
}) : super(
transitionDuration: const Duration(milliseconds: 500), // Adjust as needed
reverseTransitionDuration: const Duration(milliseconds: 500),
pageBuilder: (context, animation, secondaryAnimation) => child,
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
SlideTransition(
position: Tween(
begin: getBeginOffset(direction),
end: Offset.zero,
).animate(animation),
child: child,
),
);
static Offset getBeginOffset(AxisDirection direction) {
switch (direction) {
case AxisDirection.up:
return const Offset(0, 1);
case AxisDirection.down:
return const Offset(0, -1);
case AxisDirection.left:
return const Offset(1, 0);
case AxisDirection.right:
return const Offset(-1, 0);
}
}
}
This code slides the page in from the specified direction. You can customize the begin and end properties of the Tween<Offset> to control the slide’s origin and destination.
For a Fade Transition, use:
FadeTransition(opacity: animation, child: child)
For a Scale Transition, use:
ScaleTransition(scale: animation, child: child)
For a Rotation Transition, use:
RotationTransition(turns: animation, child: child)
Step 3: Use the Custom Route
To use the custom route, push it onto the Navigator:
Navigator.of(context).push(
CustomPageRoute(child: NextPage(), direction: AxisDirection.left), // Slide in from the left
);
Complete Example with Slide Transition
Here’s a complete example that demonstrates a slide transition from the right:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Custom Transitions Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home Page'),
),
body: Center(
child: ElevatedButton(
child: Text('Go to Next Page'),
onPressed: () {
Navigator.of(context).push(
CustomPageRoute(child: NextPage(), direction: AxisDirection.left), // Slide in from the left
);
},
),
),
);
}
}
class NextPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Next Page'),
),
body: Center(
child: Text('This is the Next Page!'),
),
);
}
}
class CustomPageRoute extends PageRouteBuilder {
final Widget child;
final AxisDirection direction;
CustomPageRoute({
required this.child,
this.direction = AxisDirection.right, // Default slide from right
}) : super(
transitionDuration: const Duration(milliseconds: 500), // Adjust as needed
reverseTransitionDuration: const Duration(milliseconds: 500),
pageBuilder: (context, animation, secondaryAnimation) => child,
transitionsBuilder: (context, animation, secondaryAnimation, child) =>
SlideTransition(
position: Tween(
begin: getBeginOffset(direction),
end: Offset.zero,
).animate(animation),
child: child,
),
);
static Offset getBeginOffset(AxisDirection direction) {
switch (direction) {
case AxisDirection.up:
return const Offset(0, 1);
case AxisDirection.down:
return const Offset(0, -1);
case AxisDirection.left:
return const Offset(1, 0);
case AxisDirection.right:
return const Offset(-1, 0);
}
}
}
Combining Transitions
You can also combine multiple transitions to create more complex effects. For instance, you could combine a fade and a slide transition:
transitionsBuilder: (context, animation, secondaryAnimation, child) {
return FadeTransition(
opacity: animation,
child: SlideTransition(
position: Tween(
begin: Offset(1, 0),
end: Offset.zero,
).animate(animation),
child: child,
),
);
}
Tips for Effective Custom Transitions
- Keep it Subtle: Overly complex transitions can distract the user.
- Performance: Optimize animations to ensure smooth performance. Avoid unnecessary calculations or complex widgets within the transition.
- Consistency: Maintain consistency in transition styles throughout your app.
- Test Thoroughly: Test transitions on different devices to ensure they work as expected.
Conclusion
PageRouteBuilder in Flutter provides the flexibility to create custom transitions that match your app’s unique style and enhance user experience. By understanding and utilizing the various transition widgets and animation properties, you can create engaging and memorable navigation experiences.