Moving Widget in flutter - flutter

I am trying to make a screen that
an image moves to a specific locatiob by clikcing a button.
I found an animation, AnimatedAligned, however this class seems not allow the widget to be located back to the original location.
Any guru knows which animation can be used in this case?

Check this out...
class SlideTransitionHome extends StatefulWidget {
#override
_SlideTransitionHomeState createState() => _SlideTransitionHomeState();
}
class _SlideTransitionHomeState extends State<SlideTransitionHome>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Tween<Offset> controllerTween = Tween<Offset>(begin: Offset.zero, end: Offset(1,1));
#override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
}
#override
void dispose() {
super.dispose();
_controller.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Center(
child: SlideTransition(
position: _controller.drive(controllerTween),
child: Container(
decoration: BoxDecoration(
color: Colors.pink,
borderRadius: BorderRadius.circular(10),
),
width: 100,
height: 100,
),
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: (){
_controller.isDismissed ? _controller.forward() : _controller.reverse();
},
),
);
}
}
The Output:
UPDATE:
If you want it to animate to the center of the top, use this as the tween.
Tween<Offset> controllerTween = Tween<Offset>(begin: Offset.zero, end: Offset(0,-2.55));
The output:

Related

Animate button rotation

I'm trying to animate rotation of icon inside custom button to 180 degree on each press. I'm bit confused from the flutter documentation. I know I should use RotationTransition but I just can not find out how.. Here is my button
SizedBox.fromSize(
size: Size(50, 50),
child: ClipOval(
child: Material(
color: Colors.blue,
child: InkWell(
onTap: () {},
splashColor: Colors.black12,
child: RotationTransition(. //<== that is where I get
child: Icon(
Icons.filter_list, //rotate this icon
color: Colors.white,
),
),
),
),
),
),
Basically, you need a Stateful widget with an AnimationController which creates controls the animation. It's important to create that controller on the initState() method, and dispose it on the dispose() method to prevent possible errors.
Once you have the controller, you can use a bool to store the rotation direction and an Animation controlled by the Animation controller to rotate the widget. First, it goes from 0 to 0.5, and then from 0.5 to 1.
The code can be like this. You can also take a look at this codepen I created for the example.
import 'package:flutter/material.dart';
void main() {
runApp(
MaterialApp(
home: MyWidget(),
),
);
}
class MyWidget extends StatefulWidget{
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin{
AnimationController _controller;
Animation<double> _animation;
bool dir = true;
#override
void initState(){
_controller = AnimationController(vsync: this, duration: Duration(seconds: 1));
super.initState();
}
#override
void dispose(){
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
_animation = Tween<double>(
begin: dir ? 0:0.5,
end: dir ? 0.5:1
).animate(_controller);
return Scaffold(
body: Center(
child: RotationTransition(
turns: _animation,
child: RaisedButton(
child: Text("Rotate"),
onPressed: (){
_controller.forward(
from: 0
);
setState(() {dir = !dir;});
}
)
)
),
);
}
}

animate widgets based on condition in scaffold body

I have a widget, with a scaffold. His body is x widget, how do I animate in the y widget on the body instead of the x widget?
The widgets are like:
Scaffold(
body: condition ? X() : Y(),
)
When the condition goes from true to false or false to true, I want the Y or X widget to animate in. How can I do this?
You can change the Offset values to get your desired result
class Test extends StatefulWidget {
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test>
with SingleTickerProviderStateMixin {
bool condition;
AnimationController _controller;
Animation<Offset> _offsetAnimation;
#override
void initState() {
condition = false;
_controller = AnimationController(
duration: const Duration(seconds: 1),
vsync: this,
);
_offsetAnimation =
Tween<Offset>(begin: Offset(0.0, -5.0), end: Offset.zero)
.animate(CurvedAnimation(
curve: Curves.linear,
parent: _controller,
));
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: InkWell(
onTap: () {
setState(() {
condition = true;
});
_controller.forward();
},
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
color: Colors.red,
width: 200,
height: 200,
),
if (condition)
SlideTransition(
position: _offsetAnimation,
child: Container(
color: Colors.green,
width: 100,
height: 100,
),
),
],
),
),
),
);
}
}

How to use SlideTransition properly?

I am trying to animate an image (or logo) from center of the screen to top of the screen.
For that, I had a look at SlideTransition. It works, but for portrait orientation only. When the device is rotated, the image goes outside of the screen. (maybe I did not understand the Offset property correctly!) If I make it work for horizontal, the output of the portrait gets changed.
Let me show you the output:
Portrait:
Before animation
After animation (As wanted)
Horizontal:
Before animation
After animation (Problem HERE)
So, as you can see, in horizontal mode, the Logo goes out of the screen.
Here is the code:
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SlideTransition Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<Offset> _offsetAnimation;
#override
void initState() {
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: 300));
_offsetAnimation = _controller
.drive(CurveTween(curve: Curves.easeInOut))
.drive(Tween<Offset>(begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0)));
super.initState();
}
#override
void dispose() {
_controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SlideTransition Demo'),
),
body: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: SlideTransition(
position: _offsetAnimation,
child: FlutterLogo(
size: 200,
),
),
),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () {
if (_controller.status == AnimationStatus.completed) {
_controller.reverse();
} else if (_controller.status == AnimationStatus.dismissed) {
_controller.forward();
}
},
child: Icon(Icons.play_arrow),
),
);
}
}
The SlideTransition does the fractional translation. And this translation depends on the size of the child of the SlideTransition widget.
Tween(begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0))
This tween translates(moves) the FlutterLogo in y-axis for 200(height of the FlutterLogo widget)
Tween(begin: Offset(0.0, 0.0), end: Offset(0.0, -0.5))
This tween translates(moves) the FlutterLogo in y-axis for 100(half-height of the FlutterLogo widget)
If you just want to animate the image from center to topCenter, then you can use AlignTransition.
Example:
class FirstPage extends StatefulWidget {
#override
FirstPageState createState() => FirstPageState();
}
class FirstPageState extends State<FirstPage> with TickerProviderStateMixin {
AnimationController _animationController;
AlignmentGeometryTween _tween;
#override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 3),
);
_tween = AlignmentGeometryTween(
begin: Alignment.center,
end: Alignment.topCenter,
);
}
TickerFuture _play() {
_animationController.reset();
return _animationController.animateTo(
1.0,
curve: Curves.easeInOut,
);
}
#override
void dispose() {
_animationController.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(title: Text("Demo")),
body: AlignTransition(
alignment: _tween.animate(_animationController),
child: FlutterLogo(
size: 200,
),
),
floatingActionButton: FloatingActionButton(
child: Icon(Icons.play_arrow),
onPressed: _play,
),
),
);
}
}
Demo: DartPad
You can copy paste run full code below
You can use OrientationBuilder and modify Offset to what you need
code snippet
body: OrientationBuilder(
builder: (context, orientation) {
if (orientation == Orientation.portrait) {
_offsetAnimation = _controller
.drive(CurveTween(curve: Curves.easeInOut))
.drive(Tween<Offset>(
begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0)));
} else {
_offsetAnimation = _controller
.drive(CurveTween(curve: Curves.easeInOut))
.drive(Tween<Offset>(
begin: Offset(0.0, 0.0), end: Offset(-1.0, 0.0)));
}
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SlideTransition Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation<Offset> _offsetAnimation;
Animation<Offset> _offsetAnimationLandscape;
#override
void initState() {
_controller =
AnimationController(vsync: this, duration: Duration(milliseconds: 300));
super.initState();
}
#override
void dispose() {
_controller?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('SlideTransition Demo'),
),
body: OrientationBuilder(
builder: (context, orientation) {
if (orientation == Orientation.portrait) {
_offsetAnimation = _controller
.drive(CurveTween(curve: Curves.easeInOut))
.drive(Tween<Offset>(
begin: Offset(0.0, 0.0), end: Offset(0.0, -1.0)));
} else {
_offsetAnimation = _controller
.drive(CurveTween(curve: Curves.easeInOut))
.drive(Tween<Offset>(
begin: Offset(0.0, 0.0), end: Offset(-1.0, 0.0)));
}
return Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: SlideTransition(
position: _offsetAnimation,
child: FlutterLogo(
size: 200,
),
),
),
],
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: () {
if (_controller.status == AnimationStatus.completed) {
_controller.reverse();
} else if (_controller.status == AnimationStatus.dismissed) {
_controller.forward();
}
},
child: Icon(Icons.play_arrow),
),
);
}
}

Starting An Animation When A Button Is Pressed - Flutter

I'm new to flutter and I'm trying to create a UI in which there is a card deck and a displayed card. Whenever the user presses on the card deck I want a new Card to show up (using an animation of flipping and moving with Positioned widget).
The thing is, I can't understand how to make the animation appear every time the widget is created.
I tried to make the animation go on the init state of the widget I created, but that doesn't seem to work.
This is the app widget tree:
class _DeckState extends State<Deck> with TickerProviderStateMixin {
List<MyCard> _cards= <MyCard>[];
#override
void initState() {
super.initState();
_cards.insert(0, MyCard());
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("NLP Deck"),
),
body: Stack(
alignment: Alignment.center,
children: <Widget>[
Container(),
_cards[0],
Positioned(
top: 40.0,
child: GestureDetector(
onTap: PressedDeck,
child: Container(
width: 100.0,
height: 128.0,
decoration: BoxDecoration(color: Colors.brown),
),
),
),
],
),
);
}
void PressedDeck() {
setState(() {
_cards.insert(0, new MyCard());
});
}
}
And this is the Card widget I created (used Containers to represent the card and the card deck):
class _CardState extends State<MyCard> with TickerProviderStateMixin {
AnimationController animController;
Animation flipAnimation;
Animation positionAnimation;
#override
void initState() {
super.initState();
animController = new AnimationController(
vsync: this, duration: Duration(milliseconds: 1000));
flipAnimation = Tween<double>(begin: 1.0, end: 0).animate(animController);
positionAnimation =
Tween<double>(begin: 40.0, end: 240.0).animate(animController);
animController.forward();
}
#override
Widget build(BuildContext context) {
return PositionTransition(
position: positionAnimation,
flip: flipAnimation,
);
}
#override
void dispose() {
animController.dispose();
super.dispose();
}
}
class PositionTransition extends AnimatedWidget {
PositionTransition({
#required Animation<double> position,
#required this.flip,
}) : super(listenable: position);
final Animation<double> flip;
#override
Widget build(BuildContext context) {
final position = super.listenable as Animation<double>;
return Positioned(
top: position.value,
child: Transform(
alignment: FractionalOffset.center,
transform: Matrix4.rotationX(math.pi * flip.value),
child: flip.value >= 0.5
? Container(
width: 100,
height: 128,
decoration: BoxDecoration(color: Colors.deepOrange),
)
: Container(
width: 100,
height: 128,
decoration: BoxDecoration(color: Colors.amber),
),
),
);
}
}
Thanks!
You can copy paste run full code below
You can call animController.reset() and forward() in didUpdateWidget
For demo purpose, I change animation duration to 3 seconds
for detail you can reference https://medium.com/sk-geek/flutter-experiment-to-trigger-animation-when-parent-setstate-84e949530b64
code snippet
#override
void didUpdateWidget(MyCard oldWidget) {
animController.reset();
animController.forward();
super.didUpdateWidget(oldWidget);
}
working demo
full code
import 'package:flutter/material.dart';
import 'dart:math' as math;
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Deck(),
);
}
}
class Deck extends StatefulWidget {
#override
_DeckState createState() => _DeckState();
}
class _DeckState extends State<Deck> with TickerProviderStateMixin {
List<MyCard> _cards = <MyCard>[];
#override
void initState() {
super.initState();
_cards.insert(0, MyCard());
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("NLP Deck"),
),
body: Stack(
alignment: Alignment.center,
children: <Widget>[
Container(),
_cards[0],
Positioned(
top: 40.0,
child: GestureDetector(
onTap: PressedDeck,
child: Container(
width: 100.0,
height: 128.0,
decoration: BoxDecoration(color: Colors.brown),
),
),
),
],
),
);
}
void PressedDeck() {
print("PressedDeck");
setState(() {
_cards.insert(0, new MyCard());
});
print("cards length ${_cards.length}");
}
}
class MyCard extends StatefulWidget {
#override
_MyCardState createState() => _MyCardState();
}
class _MyCardState extends State<MyCard> with TickerProviderStateMixin {
AnimationController animController;
Animation flipAnimation;
Animation positionAnimation;
#override
void initState() {
print("My card init State");
super.initState();
animController =
new AnimationController(vsync: this, duration: Duration(seconds: 3));
flipAnimation = Tween<double>(begin: 1.0, end: 0).animate(animController);
positionAnimation =
Tween<double>(begin: 40.0, end: 240.0).animate(animController);
animController.forward();
}
#override
void didUpdateWidget(MyCard oldWidget) {
animController.reset();
animController.forward();
super.didUpdateWidget(oldWidget);
}
#override
Widget build(BuildContext context) {
return PositionTransition(
position: positionAnimation,
flip: flipAnimation,
);
}
#override
void dispose() {
animController.dispose();
super.dispose();
}
}
class PositionTransition extends AnimatedWidget {
PositionTransition({
#required Animation<double> position,
#required this.flip,
}) : super(listenable: position);
final Animation<double> flip;
#override
Widget build(BuildContext context) {
final position = super.listenable as Animation<double>;
return Positioned(
top: position.value,
child: Transform(
alignment: FractionalOffset.center,
transform: Matrix4.rotationX(math.pi * flip.value),
child: flip.value >= 0.5
? Container(
width: 100,
height: 128,
decoration: BoxDecoration(color: Colors.deepOrange),
)
: Container(
width: 100,
height: 128,
decoration: BoxDecoration(color: Colors.amber),
),
),
);
}
}

How to rotate an image using Flutter AnimationController and Transform?

I have star png image and I need to rotate the star using Flutter AnimationController and Transformer. I couldn't find any documents or example for image rotation animation.
Any idea How to rotate an image using Flutter AnimationController and Transform?
UPDATE:
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
AnimationController animationController;
#override
void initState() {
super.initState();
animationController = new AnimationController(
vsync: this,
duration: new Duration(milliseconds: 5000),
);
animationController.forward();
animationController.addListener(() {
setState(() {
if (animationController.status == AnimationStatus.completed) {
animationController.repeat();
}
});
});
}
#override
Widget build(BuildContext context) {
return new Container(
alignment: Alignment.center,
color: Colors.white,
child: new AnimatedBuilder(
animation: animationController,
child: new Container(
height: 80.0,
width: 80.0,
child: new Image.asset('images/StarLogo.png'),
),
builder: (BuildContext context, Widget _widget) {
return new Transform.rotate(
angle: animationController.value,
child: _widget,
);
},
),
);
}
}
Full example (null safe):
Press "go" makes the star icon spin until you press "stop".
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage>
with SingleTickerProviderStateMixin {
late AnimationController _controller;
#override
void initState() {
_controller = AnimationController(
duration: const Duration(milliseconds: 5000),
vsync: this,
);
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Demo"),
),
body: Center(
child: Column(
children: <Widget>[
RotationTransition(
turns: Tween(begin: 0.0, end: 1.0).animate(_controller),
child: Icon(Icons.stars),
),
ElevatedButton(
child: Text("go"),
onPressed: () => _controller.forward(),
),
ElevatedButton(
child: Text("reset"),
onPressed: () => _controller.reset(),
),
],
),
),
);
}
}
Step by step guide:
First, let your widget state class implement SingleTickerProviderStateMixin.
Secondly, define an AnimationController and don't forget to dispose it. If you are not yet using null-safe, remove the late keyword.
late AnimationController _controller;
#override
void initState() {
_controller = AnimationController(
duration: const Duration(milliseconds: 5000),
vsync: this,
);
super.initState();
}
#override
void dispose() {
_controller.dispose();
super.dispose();
}
Then wrap your Widget with RotationTransition.
RotationTransition(
turns: Tween(begin: 0.0, end: 1.0).animate(_controller),
child: Icon(Icons.stars),
),
Finally, call methods on the AnimationController to start/stop animation.
Run the animation once, use .forward
Loop the animation, use .repeat
Stop immediately, use .stop
Stop and set it back to original rotation, use .reset
Stop and animate to a rotation value, use .animateTo
Screenshot (Null Safe)
Full code:
import 'dart:math' as math;
class _FooPageState extends State<FooPage> with SingleTickerProviderStateMixin{
late final AnimationController _controller = AnimationController(vsync: this, duration: Duration(seconds: 2))..repeat();
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: AnimatedBuilder(
animation: _controller,
builder: (_, child) {
return Transform.rotate(
angle: _controller.value * 2 * math.pi,
child: child,
);
},
child: FlutterLogo(size: 200),
),
),
);
}
}
Here my example of rotating image. I don't know - but maybe it suits for you
AnimationController rotationController;
#override
void initState() {
rotationController = AnimationController(duration: const Duration(milliseconds: 500), vsync: this);
super.initState();
}
//...
RotationTransition(
turns: Tween(begin: 0.0, end: 1.0).animate(rotationController),
child: ImgButton(...)
//...
rotationController.forward(from: 0.0); // it starts the animation
UPD - how to solve problem with Transform.rotate
In your case all works exactly as you've written - it rotates image from 0.0 to 1.0 (it's default parameters for AnimationController). For full circle you have to set upper parameter to 2 * pi (from math package)
import 'dart:math';
//...
animationController = AnimationController(vsync: this, duration: Duration(seconds: 5), upperBound: pi * 2);
Here i rotate 3 images at once... images saved in assets folder... if you want you can use network images also... i am here rotate 3 images on 3 speeds...
import 'package:flutter/material.dart';
import 'package:fynd/services/auth.dart';
import 'dart:async';
import 'package:fynd/services/cons.dart';
class SplashScreen extends StatefulWidget {
_SplashScreen createState() => new _SplashScreen();
}
class _SplashScreen extends State<StatefulWidget>
with SingleTickerProviderStateMixin {
AnimationController animationController;
#override
void initState() {
super.initState();
animationController = new AnimationController(
vsync: this,
duration: new Duration(seconds: 5),
);
animationController.repeat();
}
#override
Widget build(BuildContext context) {
return new Container(
alignment: Alignment.center,
color: Colors.white,
child: new AnimatedBuilder(
animation: animationController,
child: new Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/splash_circle3.png'))),
child: new AnimatedBuilder(
animation: animationController,
child: new Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('assets/images/splash_circle2.png'))),
child: new AnimatedBuilder(
animation: animationController,
child: Container(
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage(
'assets/images/splash_circle1.png'))),
)),
builder: (BuildContext context, Widget _widget) {
return new Transform.rotate(
angle: animationController.value * 4,
child: _widget,
);
}),
),
builder: (BuildContext context, Widget _widget) {
return new Transform.rotate(
angle: animationController.value * 5,
child: _widget,
);
},
),
),
builder: (BuildContext context, Widget _widget) {
return new Transform.rotate(
angle: animationController.value * 6,
child: _widget,
);
},
),
);
}
}
here i put the animated builder in Stack. then you can animate image rotate right(clockwise) and rotate left(anti clockwise).
import 'package:flutter/material.dart';
import 'package:fynd/services/auth.dart';
import 'dart:async';
import 'package:fynd/services/cons.dart';
class SplashScreen extends StatefulWidget {
_SplashScreen createState() => new _SplashScreen();
}
class _SplashScreen extends State<StatefulWidget>
with SingleTickerProviderStateMixin {
AnimationController animationController;
#override
void initState() {
super.initState();
animationController = new AnimationController(
vsync: this,
duration: new Duration(seconds: 5),
);
animationController.repeat();
}
#override
Widget build(BuildContext context)
return new Container(
alignment: Alignment.center,
color: Colors.white,
child: new Stack(children: <Widget>[
new AnimatedBuilder(
animation: animationController,
child :Container(
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage('assets/images/splash_circle3.png'),fit: BoxFit.cover)),
),
builder: (BuildContext context, Widget _widget) {
return new Transform.rotate(
angle: animationController.value * 10,
child: _widget,
);
},
),
new AnimatedBuilder(
animation: animationController,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage('assets/images/splash_circle2.png'),fit: BoxFit.cover)),
),
builder: (BuildContext context, Widget _widget) {
return new Transform.rotate(
angle: -animationController.value * 10,
child: _widget,
);
},
),
new AnimatedBuilder(
animation: animationController,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(image: AssetImage('assets/images/splash_circle1.png'), fit: BoxFit.cover)),
),
builder: (BuildContext context, Widget _widget) {
return new Transform.rotate(
angle: animationController.value * 10,
child: _widget,
);
}),
],),
);
}
}
Flutter also has the widget AnimatedRotation (docs) which makes rotating something much easier.
You only need a double to set the state of the rotation. It works in a percentage of rotation, if you turn it into degrees, it will be 0.0 = 0deg, 1.0 = 360deg
double turns = 0.0;
AnimatedRotation(
duration: const Duration(milliseconds: 500),
turns: turns,
child: const Icon(Icons.refresh),
)
To make the rotation happen you only need to update the state, and Flutter will execute the animation automatically
void _changeRotation() {
setState(() => turns += 1.0 / 8.0);
}
Full example taken from the Flutter docs to rotate the flutter Logo
class LogoRotate extends StatefulWidget {
const LogoRotate({Key? key}) : super(key: key);
#override
State<LogoRotate> createState() => LogoRotateState();
}
class LogoRotateState extends State<LogoRotate> {
double turns = 0.0;
void _changeRotation() {
setState(() => turns += 1.0 / 8.0);
}
#override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: _changeRotation,
child: const Text('Rotate Logo'),
),
Padding(
padding: const EdgeInsets.all(50),
child: AnimatedRotation(
turns: turns,
duration: const Duration(seconds: 1),
child: const FlutterLogo(),
),
),
],
);
}
}
class _MyHomePageState extends State<MyHomePage> with TickerProviderStateMixin {
AnimationController animationController;
#override
void initState() {
super.initState();
animationController = new AnimationController(
vsync: this,
duration: new Duration(milliseconds: 5000),
);
animationController.repeat();
}
#override
Widget build(BuildContext context) {
return new Container(
alignment: Alignment.center,
color: Colors.white,
child: RotationTransition(
child: Icon(Icons.refresh),
turns: controller,
)
);
}
}
_controller = AnimationController(duration: const Duration(seconds: 3), vsync: this);
_animation = Tween(begin: 0.0, end: 250.0).animate(_controller)
..addListener(() {
setState(() {});
})
..addStatusListener((state) {
if (state == AnimationStatus.completed) {
print("complete");
}
});
_controller.forward();
new Future.delayed(
const Duration(seconds: 5),
() => Navigator.push(
context,
MaterialPageRoute(builder: (context) => SignScreen()),
));
full example just call
ImageAnimateRotate( your widget )
class ImageAnimateRotate extends StatefulWidget {
final Widget child;
const ImageAnimateRotate({Key? key, required this.child}) : super(key: key);
#override
_ImageAnimateRotateState createState() => _ImageAnimateRotateState();
}
class _ImageAnimateRotateState extends State<ImageAnimateRotate> with SingleTickerProviderStateMixin {
late final AnimationController _controller;
#override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(seconds: 20))..repeat();
}
#override
Widget build(BuildContext context) {
return Center(
child: AnimatedBuilder(
animation: _controller,
builder: (_, child) {
return Transform.rotate(
angle: _controller.value * 2 * math.pi,
child: child,
);
},
child: widget.child,
),
);
}
}