fade in only animation in flutter - flutter

I have a home screen and I want to apply fade in animation in image and text I have a image in center and then two line of text and I just want them to fade in for the one time only I have gone through some various examples but they all contains fade in and fade out i just want to reveal thosse image and text to user and the pause.

Try with this it will fade in from initState also i delayed 1 second you can modify it.
bool _visible = false;
#override
void initState() {
Future.delayed(const Duration(seconds: 1), () {
setState(() {
_visible = !_visible;
});
});
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: AnimatedOpacity(
// If the widget is visible, animate to 0.0 (invisible).
// If the widget is hidden, animate to 1.0 (fully visible).
opacity: _visible ? 1.0 : 0.0,
duration: const Duration(milliseconds: 500),
// The green box must be a child of the AnimatedOpacity widget.
child:Column(
children:[
Image.network("https://cdn0.iconfinder.com/data/icons/business-startup-10/50/5-256.png")
,
const Text("Your text")
])
),
),
);
}

Related

how to make icon and text translation animation on flutter

how to make this animation on flutter
icon and text
the default state is the icon is shown and the text is disappears
when click the icon: the icon goes up and text goes under icon and appears
otherwise the icon goes in center and the text disappears
like this video
https://i.imgur.com/S0LXr3o.mp4
https://drive.google.com/file/d/1nwpgjOM_6TUaaVaSdsIZp0oYi4CdWSMR/view?usp=sharing
you can use AnimationController and AnimationBuilder combined with Stack + Positioned
or you can even use the Transform Widget with the same concept!
I've write an example to make the animation
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
class AnimationExerciseScreen extends StatefulWidget {
const AnimationExerciseScreen({Key? key}) : super(key: key);
#override
_AnimationExerciseScreenState createState() =>
_AnimationExerciseScreenState();
}
class _AnimationExerciseScreenState extends State<AnimationExerciseScreen>
with SingleTickerProviderStateMixin {
#override
void initState() {
super.initState();
animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 3),
);
animationController.forward();
}
#override
void dispose() {
animationController.dispose();
super.dispose();
}
late final AnimationController animationController;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
height: 100,
child: AnimatedBuilder(
animation: animationController,
builder: (context, child) => Stack(
children: [
Positioned(
top: 0 + (40 * animationController.value),
child: Icon(Icons.cloud),
),
Positioned(
bottom: 0 + (40 * animationController.value),
child: Opacity(
opacity: 1 - animationController.value,
child: Text('Cloud'),
),
),
],
),
),
),
],
),
),
);
}
}
video link:
https://imgur.com/RJg5PWw
Explanation:
the animation controller has a value of 0 to 1 with the type of double, which will represent the amount percentage of the animation
in the above example, I'm using 3 seconds duration of the animation controller so the animation will be visible to our eyes easily, so I use animationController.forward to play the animation at the initState
note: the placement of the animation is not optimized for performance, this example is just for example to understand how the animation works
if you want to optimize the animation, you can put your widget to child attribute of the AnimationBuilder for more info you can read them here and here and here and so much more! you can explore tons of articles to improve your flutter app's performance!

How to make text transition by animation upon button press?

Currently, when opacity = 0 & button is pressed, opacity becomes one. But I would like the button also having the function to turn opacity to zero and back to one when opacity is already one.
How can this be made possible ? Thanks
Im thinking it has something to do with tween? Eg. When the button is pressed, the opacity of the quote turns to zero and back to 1 (duration of one second).
But Im not sure how to write that.
Attached below is the main chunk of the code that's involved in this action:
double opacity1 = 0.0;
String quoteCat1 = List1[Random().nextInt(List1.length)];
void generateConvoTopic1() {
setState(() {
quoteCat1 = List1[Random().nextInt(List1.length)];
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
...
body: ...
AnimatedOpacity(
opacity: opacity1,
duration: Duration(seconds: 1),
child:Text(quoteCat1),
]),
...
ElevatedButton(
...
onPressed: () {
generatequoteCat1();
opacity1 = 1.0;
opacity2 = 0.0;
opacity3 = 0.0;
},),
...
If you only want to switch between two values, you could use a boolean and make your button switch its value. In the toggleOpacity function is also an example of how to animate back the function as #Aayush said using a Future.delayed.
Now if you want more complex animations, or infinite ones, you should use an animationController to have full control of it
See example:
class Demo extends StatefulWidget {
Demo({Key key, this.title}) : super(key: key);
final String title;
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
bool visible = true;
var animateBack=false;
void toggleOpacity() {
setState(() {
visible = !visible;
});
if(animateBack)
Future.delayed(Duration(seconds: 1)).then((value) {
setState(() {
visible = !visible;
});
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: AnimatedOpacity(
opacity: visible ? 1 : 0,
duration: Duration(seconds: 1),
child: Text(
'Now you see me',
),
),
),
floatingActionButton: FloatingActionButton(
onPressed: toggleOpacity,
child: Icon(visible?Icons.wb_sunny:Icons.wb_sunny_outlined),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

Make a widget in front of an overlay

I'm trying to reproduce the same contextual menu of Pinterest, in Flutter. So I have an overlay, which displays my contextual menu with a background, and I'd like to keep also the current element in front of the overlay.
Here are 2 videos: the Pinterest menu vs My Flutter menu.
To make an overlay I'm using flutter_portal package.
Here is the code of the blue card widget, with the overlay stuff:
import 'package:flutter/material.dart';
import 'package:flutter_portal/flutter_portal.dart';
import 'package:vector_math/vector_math.dart' show radians;
class CardWidget extends StatefulWidget {
#override
_CardWidgetState createState() => _CardWidgetState();
}
class _CardWidgetState extends State<CardWidget> with SingleTickerProviderStateMixin {
late AnimationController controller;
late Animation<double> degreeAnimation;
late Animation<double> opacityAnimation;
bool isMenuOpen = false;
double menuPosX = 0;
double menuPosY = 0;
#override
void initState() {
controller = AnimationController(vsync: this, duration: Duration(milliseconds: 200))
..addListener(() {
setState(() {});
})
..addStatusListener((status) {
if (status == AnimationStatus.forward) {
isMenuOpen = true;
} else if (status == AnimationStatus.dismissed) {
isMenuOpen = false;
}
});
degreeAnimation =
Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: controller, curve: Curves.easeOutBack));
opacityAnimation =
Tween(begin: 0.0, end: 1.0).animate(CurvedAnimation(parent: controller, curve: Curves.easeOutExpo));
super.initState();
}
#override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: 63.5 / 88.9,
child: PortalEntry(
visible: isMenuOpen,
portal: Container(
color: Colors.black.withOpacity(opacityAnimation.value / 2),
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
controller.reverse();
},
),
),
child: PortalEntry(
visible: isMenuOpen,
child: GestureDetector(
onTapDown: (details) {
if (controller.isCompleted) {
controller.reverse();
} else {
menuPosX = details.globalPosition.dx;
menuPosY = details.globalPosition.dy;
controller.forward();
}
},
// Blue card content
child: Container(
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.all(
Radius.circular(8),
),
),
child: Center(
child: Text(
'Card Widget',
style: TextStyle(color: Colors.white),
),
),
),
),
// Current contextual Menu
portal: ContextualMenuWidget(),
),
),
);
}
}
Thank you for your help!
Maybe instead of an trying to add an overlay, you can change the color of all the other cards to the same as the background. By that you would achieve the same effect.
You can check if isMenuOpen is true and save the index of the card on which it was clicked, and in your grid builder function you can change the color of all the cards to the same as the background.
Thanks to orotype, instead of making a black overlay, I finally wrapped my cards with an AnimatedOpacity, and passed a callback when the contextual menu is opened/closed to trig the animation.
Result here!
I don't know if this is the best solution, but I like the result.

Show modal bottom sheet with custom animation

I was playing around with showModalBottomSheet() in Flutter and I was thinking about changing the default slide from bottom animation. Looking throught flutter documentation I saw that there is in fact a BottomSheet class that accept animation as parameters but, accordingly to the page, showModalBottomSheet() is preferrable.
Is possible to control the animation in some way? I just need to change the default curve and duration.
Thanks
You can use the AnimationController drive method to modify the animation curve, and duration and reverseDuration to set how long the animation will go on. These can be declared on your initState() if you're using a StatefulWidget.
late AnimationController controller;
#override
initState() {
super.initState();
controller = BottomSheet.createAnimationController(this);
// Animation duration for displaying the BottomSheet
controller.duration = const Duration(seconds: 1);
// Animation duration for retracting the BottomSheet
controller.reverseDuration = const Duration(seconds: 1);
// Set animation curve duration for the BottomSheet
controller.drive(CurveTween(curve: Curves.easeIn));
}
Then configure the BottomSheet transtionAnimationController
showModalBottomSheet(
transitionAnimationController: controller,
builder: (BuildContext context) {
return ...
}
)
Here's a sample that you can try out.
import 'package:flutter/material.dart';
class BottomSheetAnimation extends StatefulWidget {
const BottomSheetAnimation({Key? key}) : super(key: key);
#override
_BottomSheetAnimationState createState() => _BottomSheetAnimationState();
}
class _BottomSheetAnimationState extends State<BottomSheetAnimation>
with TickerProviderStateMixin {
late AnimationController controller;
#override
initState() {
super.initState();
controller = BottomSheet.createAnimationController(this);
// Animation duration for displaying the BottomSheet
controller.duration = const Duration(seconds: 1);
// Animation duration for retracting the BottomSheet
controller.reverseDuration = const Duration(seconds: 1);
// Set animation curve duration for the BottomSheet
controller.drive(CurveTween(curve: Curves.easeIn));
}
#override
void dispose() {
controller.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'BottomSheet',
home: Scaffold(
appBar: AppBar(
title: const Text('BottomSheet'),
),
body: Center(
child: TextButton(
child: const Text("Show bottom sheet"),
onPressed: () {
showModalBottomSheet(
context: context,
transitionAnimationController: controller,
builder: (BuildContext context) {
return const SizedBox(
height: 64,
child: Text('Your bottom sheet'),
);
},
);
},
),
),
),
);
}
}
Demo

Replaying the same Flare animation in Flutter

I'm trying to re-play a Flare animation in Flutter. Not loop the animation when it has complete. I want an animation to be played on demand, the same animation.
When I switch between animations it works fine when just swapping the string and calling setState. Is there a simple way to do this.
Here's what I'm currently doing.
class _FlareDemoState extends State<FlareDemo> {
String animationToPlay = 'activate';
#override
Widget build(BuildContext context) {
print('Animation to play: $animationToPlay');
return Scaffold(
backgroundColor: Colors.purple,
body: GestureDetector(
onTap: () {
setState(() {
});
},
child: FlareActor('assets/button-animation.flr',
animation: animationToPlay)));
}
}
My logs result when I tap the animation
I/flutter (18959): Animation to play: activate
I/flutter (18959): Animation to play: activate
I/chatty (18959): uid=10088(com.example.flare_tutorial) Thread-2 identical 2 lines
I/flutter (18959): Animation to play: activate
I/flutter (18959): Animation to play: activate
I/chatty (18959): uid=10088(com.example.flare_tutorial) Thread-2 identical 7 lines
I/flutter (18959): Animation to play: activate
I/flutter (18959): Animation to play: activate
Reloaded 2 of 495 libraries in 672ms.
I/flutter (18959): Animation to play: activate
Everything is called, it plays the first time, but after that the animation doesn't replay.
A cleaner way to do this is using a custom FlareController. There's a concrete FlareControls implementation that fits this use case nicely.
class _MyHomePageState extends State<MyHomePage> {
// Store a reference to some controls for the Flare widget
final FlareControls controls = FlareControls();
void _playSuccessAnimation() {
// Use the controls to trigger an animation.
controls.play("success");
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: FlareActor("assets/Teddy.flr",
animation: "idle",
fit: BoxFit.contain,
alignment: Alignment.center,
// Make sure you use the controls with the Flare Actor widget.
controller: controls),
floatingActionButton: FloatingActionButton(
onPressed: _playSuccessAnimation,
tooltip: 'Play',
child: Icon(Icons.play_arrow),
),
);
}
}
Note that this example also plays an idle background animation which loops. Any call to FlareControls.play will mix the incoming animation over this background idle animation. You simply omit the animation: "idle" argument if you don't want/need a background animation.
Full example here: https://github.com/luigi-rosso/flare_controls
Based on the answer from #Eugene I came up with a temporary solution. I set the value to empty, start a timer for 50ms and then set the value back to the animation I wanted to play again.
class _FlareDemoState extends State<FlareDemo> {
String animationToPlay = 'activate';
#override
Widget build(BuildContext context) {
print('Animation to play: $animationToPlay');
return Scaffold(
backgroundColor: Colors.purple,
body: GestureDetector(
onTap: () {
_setAnimationToPlay('activate');
},
child: FlareActor('assets/button-animation.flr',
animation: animationToPlay)));
}
}
void _setAnimationToPlay(String animation) {
if (animation == _animationToPlay) {
_animationToPlay = '';
Timer(const Duration(milliseconds: 50), () {
setState(() {
_animationToPlay = animation;
});
});
} else {
_animationToPlay = animation;
}
}
It's messy workaround but it gets the job done. Thank you #Eugene for planting the seed.
FlareActor(
"assets/animation/day_night.flr",
alignment: Alignment.center,
fit: BoxFit.cover,
animation: _animation,
callback: (string) {
if(string=="switch_night"){
setState(() {
_animation = _animationNight;
});
}else if(string=="switch_day"){
setState(() {
_animation = _animationDay;
});
}
},
)