This blog post will show you how to change the position of a widget with an animation by using PositionedTransition widget. You’ll see that using widgets and animating them can make your app more visually appealing.
PositionedTransition widget allows for a child to move from one position to another in an animation. The animation can only happen if it is the child of a Stack widget.
Default Constructor:
PositionedTransition({ Key key, @required Animation<RelativeRect> rect, @required Widget child, });
Example:
The example below has a Container which holds a Play button. After the button is clicked, the Container moves to the center while gradually changing increasing size. When it stops at the center, clicking it again make it animate backward.


import 'package:flutter/material.dart'; class Homepage extends StatefulWidget { const Homepage({Key? key}) : super(key: key); @override _HomepageState createState() => _HomepageState(); } class _HomepageState extends State<Homepage> with SingleTickerProviderStateMixin { late final AnimationController _controller = AnimationController( duration: const Duration(seconds: 2), vsync: this, ); @override void dispose() { _controller.dispose(); super.dispose(); } Container _container() { return Container( color: Colors.red, child: IconButton( alignment: Alignment.center, icon: Icon( Icons.play_arrow, color: Colors.white, size: 36, ), onPressed: () { if(_controller.isCompleted){ _controller.reverse(); } else { _controller.forward(); } }, ), ); } @override Widget build(BuildContext context) { double smallSize = 100; double largeSize = MediaQuery.of(context).size.width; final Size screenSize = Size( MediaQuery.of(context).size.width, MediaQuery.of(context).size.height); return Scaffold( body: Stack( children: <Widget>[ PositionedTransition( rect: RelativeRectTween( begin: RelativeRect.fromSize( Rect.fromLTWH(0, 0, smallSize, smallSize), screenSize), end: RelativeRect.fromSize( Rect.fromLTWH(0, screenSize.height / 2, largeSize, 100), screenSize), ).animate(CurvedAnimation( parent: _controller, curve: Curves.elasticInOut, )), child: Padding( padding: const EdgeInsets.all(16.0), child: _container(), ), ), ], ), ); } }