Implementing Flutter Nike Animation
Animations can significantly enhance the user experience by providing visual feedback and creating a more interactive interface. Flutter, with its robust animation framework, makes it easy to create smooth and engaging animations. In this post, I'll walk you through the steps to implement this UI animation in Flutter.
Animations are an essential part of modern app development, bringing life and interactivity to user interfaces. In this blog post, we'll explore a fascinating example of an animation created with Flutter: the Nike Slider. This animation demonstrates how to use Flutter's powerful animation capabilities to create a smooth, engaging, and interactive user experience.
Understanding the Basics
The Nike Slider is a Flutter widget that animates between three different "slides," each representing a different color and image associated with the Nike brand. It uses an AnimationController
to handle the animation and several Tween
objects to define the animation's behavior.
Setting Up the Animation
First, let's look at the initialization process. The AnimationController
is set up in the initState
method of the _HomeScreenState
class. This controller manages the duration and the state of the animation.
main.dart
int activeIndex = 5;
final duration = const Duration(milliseconds: 400);
AnimationController? _controller;
Animation<double>? _widthAnimation;
Animation<double>? _textTranslationAnimation;
Animation<double>? _widthReduceAnimation;
Animation<double>? _rotationAnimation;
bool hasReversed = false;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: duration);
Timer(Duration(seconds: 2), () {
setAnimatedValues(5, context);
});
}
Defining the Animation Values
The setAnimatedValues
method sets up the various animations that will be used. These include animations for the width, text translation, width reduction, and rotation.
main.dart
curve(ctrl) => CurvedAnimation(parent: ctrl, curve: Curves.linear);
setAnimatedValues(int index, BuildContext? context) {
if (context != null) {
_widthAnimation = Tween<double>(
begin: Sizing.width(context) / 3,
end: Sizing.width(context),
).animate(curve(_controller!));
_textTranslationAnimation = Tween<double>(
begin: 1.8,
end: 2.5,
).animate(curve(_controller!));
_widthReduceAnimation = Tween<double>(
begin: Sizing.width(context) / 3,
end: 0,
).animate(curve(_controller!));
_rotationAnimation = Tween<double>(
begin: -0.7,
end: -0.1,
).animate(curve(_controller!));
}
}
Building the Widget Tree
The main widget tree for the Nike Slider is built in the build
method. It consists of three primary components: the sliding containers, a follow button, and a navigation bar.
main.dart
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: [
Positioned(
top: 0,
left: 0,
right: 0,
child: Row(
children: [
...[0, 1, 2].map(
(index) {
return AnimatedBuilder(
animation: _controller!,
builder: (context, _) {
return nikeSlide(context, index);
},
);
},
).toList()
],
),
),
Positioned(
bottom: 20,
left: 0,
right: 0,
child: Follow(activeIndex: activeIndex),
),
Positioned(
top: 0,
left: 0,
right: 0,
child: NavBar(),
),
],
),
);
}
Creating the Sliding Containers
Each sliding container is created using the nikeSlide
method, which builds a container with the appropriate color, size, and content based on the current animation values.
main.dart
Container nikeSlide(BuildContext context, int index) {
// Animated width
final a_w = _widthAnimation?.value??Sizing.width(context)/3;
// Reduced animated width
final r_w = _widthReduceAnimation?.value??Sizing.width(context)/3;
return Container(
clipBehavior: Clip.hardEdge,
decoration: BoxDecoration(
color: index == 0
? AppColors.blue
: index == 1
? AppColors.red
: AppColors.yellow,
),
width: index == activeIndex ? a_w: r_w,
height: Sizing.height(context),
child: Stack(
clipBehavior: Clip.hardEdge,
children: [
Positioned(
top: 0,
bottom: 0,
left: 0,
right: 0,
child: Center(
child: Transform.scale(
scale: _textTranslationAnimation?.value ?? 1.8,
child: Text(
overflow: TextOverflow.ellipsis,
index == 0
? "BLUE"
: index == 1
? "RED"
: "YELLOW",
style: GoogleFonts.montserrat(
fontSize: 100,
fontWeight: FontWeight.w800,
color: AppColors.white,
fontStyle: FontStyle.italic,
),
),
),
),
),
Positioned(
top: 0,
bottom: 0,
left: 0,
right: 0,
child: InkWell(
onTap: () => _toggleAnimation(index),
child: Transform.rotate(
angle: _rotationAnimation?.value ?? -0.7,
child: Image.asset("assets/images/nike_${index}.png"),
),
),
),
],
),
);
}
Toggling the Animation
The _toggleAnimation
method handles the animation state when a container is tapped. It toggles between the forward and reverse states of the animation, providing a smooth transition effect.
main.dart
void _toggleAnimation(int index) async {
if (index == activeIndex) {
if (hasReversed) {
_controller?.forward();
setState(() => hasReversed = !hasReversed);
} else {
_controller?.reverse();
setState(() => hasReversed = !hasReversed);
}
} else {
_controller?.forward();
}
setState(() => activeIndex = index);
}
Complete Code
You can find the complete source code of this tutorial on here! . If you enjoy it, please leave a star on the repo and comment below!
Conclusion
The Nike Slider example showcases the power and flexibility of Flutter's animation framework. By combining various animations and leveraging Flutter's widget tree, you can create highly interactive and visually appealing user interfaces. Whether you're building a simple app or a complex user experience, mastering Flutter animations will undoubtedly enhance the quality and engagement of your applications.
Comments