Animations are an integral part of modern mobile app development. They enhance user experience by providing visual feedback, making transitions smoother, and adding a touch of delight. Flutter, Google’s UI toolkit, offers a rich set of animation capabilities through its various animation packages. In this article, we’ll dive into the animations package in Flutter, exploring its features and how you can use it to create beautiful and engaging animations.
What is the animations Package?
The animations package in Flutter provides a collection of pre-built, ready-to-use animations that can be easily integrated into your Flutter applications. It simplifies the process of creating common UI transitions and effects, such as container transformations, fade-through animations, and more. This package is part of the Flutter ecosystem and is designed to work seamlessly with Flutter’s animation framework.
Why Use the animations Package?
- Simplified Animations: Reduces the complexity of creating common animations.
- Pre-Built Components: Offers ready-to-use animation widgets, saving development time.
- Customizable: Provides flexibility to customize animations to fit your specific design requirements.
- Improved UX: Enhances user experience by providing smooth and engaging transitions.
Setting Up the animations Package
Before you start using the animations package, you need to add it to your project’s dependencies.
Step 1: Add Dependency
Open your pubspec.yaml file and add the animations package under the dependencies section:
dependencies:
flutter:
sdk: flutter
animations: ^2.0.7 # Use the latest version
Then, run flutter pub get to install the package.
Step 2: Import the Package
In your Dart file, import the animations package:
import 'package:animations/animations.dart';
Key Features and Usage
The animations package provides several key features that make it easy to add polished animations to your Flutter app.
1. PageTransitionsTheme
The PageTransitionsTheme allows you to define consistent page transitions across your entire application. You can specify different transition types for different platforms (Android, iOS, etc.).
Example:
import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Animations Example',
theme: ThemeData(
pageTransitionsTheme: PageTransitionsTheme(
builders: {
TargetPlatform.android: FadeThroughPageTransitionsBuilder(),
TargetPlatform.iOS: CupertinoPageTransitionsBuilder(),
},
),
),
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Home'),
),
body: Center(
child: ElevatedButton(
child: Text('Go to Next Page'),
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => NextPage()),
);
},
),
),
);
}
}
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.'),
),
);
}
}
In this example, FadeThroughPageTransitionsBuilder is used for Android, and CupertinoPageTransitionsBuilder for iOS, providing platform-specific page transitions.
2. OpenContainer
The OpenContainer widget allows you to create a seamless transition between two screens. It’s particularly useful for master-detail views where a user taps on an item to view its details.
Example:
import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
class OpenContainerExample extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('OpenContainer Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: OpenContainer(
transitionDuration: Duration(milliseconds: 500),
openBuilder: (BuildContext context, VoidCallback _) => DetailPage(),
closedBuilder: (BuildContext context, VoidCallback openContainer) =>
Container(
height: 100,
width: double.infinity,
color: Colors.blue,
child: Center(
child: Text(
'Tap to Open',
style: TextStyle(color: Colors.white),
),
),
),
),
),
);
}
}
class DetailPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Detail Page'),
),
body: Center(
child: Text('This is the detail page.'),
),
);
}
}
In this example, tapping on the container with the text “Tap to Open” smoothly transitions to the DetailPage using the default container transform animation.
3. SharedAxisTransition
SharedAxisTransition provides a set of animations that create a visual connection between two elements that share a common axis (X, Y, or Z). This is helpful for creating transitions between different parts of the same screen or different screens that are logically related.
Example:
import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
class SharedAxisTransitionExample extends StatefulWidget {
@override
_SharedAxisTransitionExampleState createState() =>
_SharedAxisTransitionExampleState();
}
class _SharedAxisTransitionExampleState
extends State {
int _currentPageIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SharedAxisTransition Example'),
),
body: PageTransitionSwitcher(
duration: Duration(milliseconds: 500),
transitionBuilder: (
Widget child,
Animation animation,
Animation secondaryAnimation,
) {
return SharedAxisTransition(
child: child,
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.horizontal,
);
},
child: [
Container(
key: ValueKey(0),
color: Colors.red,
child: Center(
child: Text(
'Page 1',
style: TextStyle(color: Colors.white),
),
),
),
Container(
key: ValueKey(1),
color: Colors.green,
child: Center(
child: Text(
'Page 2',
style: TextStyle(color: Colors.white),
),
),
),
][_currentPageIndex],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentPageIndex,
onTap: (index) {
setState(() {
_currentPageIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Page 2',
),
],
),
);
}
}
In this example, the SharedAxisTransition is used to transition between two pages with a horizontal axis transition.
4. FadeThroughTransition
FadeThroughTransition is a subtle transition where the outgoing content fades out and the incoming content fades in. It is suitable for transitioning between loosely related screens.
Example:
import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
class FadeThroughTransitionExample extends StatefulWidget {
@override
_FadeThroughTransitionExampleState createState() =>
_FadeThroughTransitionExampleState();
}
class _FadeThroughTransitionExampleState
extends State {
int _currentPageIndex = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FadeThroughTransition Example'),
),
body: PageTransitionSwitcher(
duration: Duration(milliseconds: 500),
transitionBuilder: (
Widget child,
Animation animation,
Animation secondaryAnimation,
) {
return FadeThroughTransition(
child: child,
animation: animation,
secondaryAnimation: secondaryAnimation,
);
},
child: [
Container(
key: ValueKey(0),
color: Colors.yellow,
child: Center(
child: Text(
'Page 1',
style: TextStyle(color: Colors.black),
),
),
),
Container(
key: ValueKey(1),
color: Colors.cyan,
child: Center(
child: Text(
'Page 2',
style: TextStyle(color: Colors.black),
),
),
),
][_currentPageIndex],
),
bottomNavigationBar: BottomNavigationBar(
currentIndex: _currentPageIndex,
onTap: (index) {
setState(() {
_currentPageIndex = index;
});
},
items: [
BottomNavigationBarItem(
icon: Icon(Icons.home),
label: 'Page 1',
),
BottomNavigationBarItem(
icon: Icon(Icons.business),
label: 'Page 2',
),
],
),
);
}
}
In this example, the FadeThroughTransition is used to create a smooth transition between two pages.
5. FadeScaleTransition
FadeScaleTransition combines a fade and scale effect to transition between widgets. It is useful for creating transitions where an element fades in while scaling up or down.
Example:
import 'package:flutter/material.dart';
import 'package:animations/animations.dart';
class FadeScaleTransitionExample extends StatefulWidget {
@override
_FadeScaleTransitionExampleState createState() =>
_FadeScaleTransitionExampleState();
}
class _FadeScaleTransitionExampleState
extends State {
bool _isExpanded = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('FadeScaleTransition Example'),
),
body: Center(
child: OpenContainer(
transitionDuration: Duration(milliseconds: 500),
openBuilder: (BuildContext context, VoidCallback _) {
return Scaffold(
appBar: AppBar(title: Text('Expanded View')),
body: Center(
child: Text('This is the expanded view.'),
),
);
},
closedBuilder: (BuildContext context, VoidCallback openContainer) {
return Container(
width: 200,
height: 100,
child: Center(
child: Text(
'Tap to Expand',
style: TextStyle(color: Colors.white),
),
),
color: Colors.purple,
);
},
closedElevation: 6.0,
openElevation: 0.0,
closedShape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12.0)),
),
),
),
);
}
}
In this example, FadeScaleTransition is used within an OpenContainer to provide a visual transition when the container expands.
Best Practices for Using Animations
When implementing animations in your Flutter app, consider the following best practices:
- Keep Animations Short: Short animations (200-500ms) feel more responsive.
- Use Subtlety: Animations should enhance, not distract.
- Be Consistent: Use consistent animation patterns throughout your app.
- Test on Different Devices: Ensure animations perform well on low-end devices.
Conclusion
The animations package in Flutter offers a streamlined way to incorporate engaging and visually appealing animations into your applications. By leveraging pre-built components like OpenContainer, SharedAxisTransition, and FadeThroughTransition, you can enhance the user experience with minimal effort. Understanding how to properly integrate and customize these animations can significantly elevate the overall quality and polish of your Flutter apps.