Using AnimatedPositioned Widget In Flutter
Flutter is an amazing UI tool kit used to create beautiful applications with ease. Flutter provides us a variety of widgets that can be used to create animated and customs widgets.
In this blog, we shall explore AnimatedPositioned
widget and we will create a custom screen view demo using Animation and AnimatedPositioned
. So let’s get started.
Module Demo :
Note: You can read the full blog here.
Table of Content
:: Intializing Objects and variables
AnimatedPositioned Widget
This widget is used to animate the position of a widget implicitly. It fits into a stack list of children just like a regular Positioned
widget. It animates the given child position according to the curve, position, and duration specified by the user.
The properties of AnimatedPositioned are: left
, right
,top
, bottom
, duration
, child
,width
, onEnd
, height
, curve
and key
.
Read more about Animation:
Introduction to Animation in Flutter
Let’s learn how to animate flutter widgets…medium.com
Creating a Custom Sreen View
Creating a MainSreen stateful class with SingleTickerProviderStateMixin
SingleTickerProviderStateMixin
used when you have only one Animation Controller in your widget and its job is to provide with ticker value to the Stateful Widget.
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> with SingleTickerProviderStateMixin{
@override
Widget build(BuildContext context) {
return Container();
}
}
Initializing Objects and variables
Here we have created 4 bool variables to control the animated position of the widget and _controller
the object is used to control the animation of the widget and duration
controls the animation duration of the widget.
class MainScreen extends StatefulWidget {
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> with SingleTickerProviderStateMixin{
bool isLeftCollapsed = true;
bool isRightCollapsed = true;
bool isTopCollapsed = true;
bool isBottomCollapsed = true;
double screenWidth, screenHeight;
final Duration duration = const Duration(milliseconds: 300);
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: duration);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold();
}
}
Stack
AnimatedPostioned widget can only be only inside the stack children widgets, so we need to use Stack
widget to wrap all our widgets inside it.
Scaffold(
body: Stack(
children: <Widget>[
upperBar(),
sideBar(),
bottomBar(),
AnimatedPositioned(
left: isLeftCollapsed ? 0 : 0.5 * screenWidth,
right: isRightCollapsed ? 0 : -0.2 * screenWidth,
top: isTopCollapsed ? 0 : 0.1 * screenHeight,
bottom: isBottomCollapsed ? 0 : 0.1 * screenHeight,
duration: duration,
child: dashboard(context)),
],
),
);
Other Widgets
These widgets are used as a part of the demo UI. bottomBar()
, upperBar()
,sideBar()
widget is used at the bottom of our screen, top of our screen, and left side of the screen respectively.
Widget bottomBar() {
return Positioned(
bottom: 10,
left: 30,
child: Row(
children: [
Text(
"Reset Password",
style: TextStyle(color: Colors.grey, fontSize: 25),
),
SizedBox(
width: 60,
),
Container(
width: 100,
height: 40,
child: Center(
child: Text(
"Log Out",
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), color: Colors.blue),
)
],
));
}
Widget sideBar() {
return Positioned(
left: 30,
top: 250,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Home",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.blue,
fontSize: 25),
),
SizedBox(
height: 10,
),
Text(
"My Account",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.blue,
fontSize: 25),
),
SizedBox(
height: 10,
),
Text(
"My Orders",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.blue,
fontSize: 25),
),
SizedBox(
height: 10,
),
Text(
"Settings",
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.blue,
fontSize: 25),
),
],
));
}
Widget upperBar() {
return Positioned(
top: 40,
left: 30,
child: Row(
children: [
CircleAvatar(
child: Icon(Icons.person_outline),
),
SizedBox(
width: 10,
),
Text(
"User name",
style: TextStyle(fontSize: 25, fontWeight: FontWeight.bold),
),
SizedBox(
width: 80,
),
Container(
width: 100,
height: 40,
child: Center(
child: Text(
"View Profile",
style:
TextStyle(color: Colors.white, fontWeight: FontWeight.bold),
)),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10), color: Colors.blue),
)
],
));
}
Building dashboard
dashboard()
widgets is used at the top of our Stack
this widget is going to be animated. In this widget I have created an icon Button the AppBar
that will animate the position of dashborad()
the widget from the top
, bottom
and left
side of the screen, this can also be used as a custom drawer
as it looks like a side drawer. Also, we have Animated the top and bottom of the dashboard()
.
Logic used
When the user will tap the menu icon the animation will start and isTopCollapsed
, isBottomCollapsed
, isLeftCollapsed
variables will set to there not values i.e. if they are true then they will set to false and vise versa.
When all three variables are false the AnimatedPostioned
widget that we have used inside our Stack
will animate the position of dashborad()
widgets.
AnimatedPositioned(
left: isLeftCollapsed ? 0 : 0.5 * screenWidth,
right: isRightCollapsed ? 0 : -0.2 * screenWidth,
top: isTopCollapsed ? 0 : 0.1 * screenHeight,
bottom: isBottomCollapsed ? 0 : 0.1 * screenHeight,
duration: duration,
child: dashboard(context)),
Widget dashboard(context) {
return SafeArea(
child: Material(
type: MaterialType.card,
animationDuration: duration,
elevation: 8,
child: Scaffold(
appBar: AppBar(
elevation: 0,
title: Text('MarketWatch'),
actions: [
IconButton(
icon: isTopCollapsed
? Icon(
Icons.keyboard_arrow_down_outlined,
size: 40,
color: Colors.white,
)
: Icon(
Icons.keyboard_arrow_up_outlined,
size: 40,
color: Colors.white,
),
onPressed: () {
setState(() {
isTopCollapsed
? _controller.forward()
: _controller.reverse();
isTopCollapsed = !isTopCollapsed;
});
},
)
],
leading: IconButton(
icon: isLeftCollapsed ? Icon(Icons.menu) : Icon(Icons.clear),
onPressed: () {
setState(() {
if (isLeftCollapsed) {
_controller.forward();
} else {
_controller.reverse();
}
isTopCollapsed = !isTopCollapsed;
isLeftCollapsed = !isLeftCollapsed;
isBottomCollapsed = !isBottomCollapsed;
});
}),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
setState(() {
isBottomCollapsed
? _controller.forward()
: _controller.reverse();
isBottomCollapsed = !isBottomCollapsed;
});
},
child: isBottomCollapsed
? Icon(
Icons.keyboard_arrow_up_outlined,
size: 40,
)
: Icon(
Icons.keyboard_arrow_down_outlined,
size: 40,
),
),
),
),
);
}
main.dart file
https://gist.github.com/anmolseth06/bd391505d4c257a2f74a199ac2f47231#file-main-dart
Thanks for reading this article ❤
If I got something wrong? Let me know in the comments. I would love to improve.
Clap 👏 If this article helps you.
If we got something wrong? Let me know in the comments. we would love to improve.
FlutterDevs team of Flutter developers to build high-quality and functionally-rich apps. Hire a flutter developer for your cross-platform Flutter mobile app project on an hourly or full-time basis as per your requirement! You can connect with us on Facebook, GitHub, Twitter, and LinkedIn for any flutter related queries.
We welcome feedback and hope that you share what you’re working on using #FlutterDevs. We truly enjoy seeing how you use Flutter to build beautiful, interactive web experiences!.