Flutter: animate layout changes - flutter

Is it possible to animate page items as they appear? (not with fade effect) like on android, with
android:animateLayoutChanges
Example 1
Example 2.

You can try delayed_display pub package.
But if you want to do something custom, for example:
AnimatedContainer(
duration: Duration(milliseconds: 500),
height: 50,
width: isVisible ? 100 : 50,
color: isVisible ? Colors.yellow : Colors.blue,
);

Related

How to animate color transitions in flutter?

I'm creating a custom checkbox-like widget that uses Card. I'm able to get the colors changing if the values are the same onTap. However, I want it to transition the color instead of it suddenly changing.
Here's my code:
return Card(
color: selected ? AppColors.primary : AppColors.primaryLight,
I'm relatively new to animations in Flutter, but coming from a strong Frontend/CSS understanding, the way I could achieve something like this is to add transition on a CSS property -- is there something similar to this in Flutter? If not, could someone point me in the right direction?
What I would do is instead of using the Card widget, I would use an AnimatedContainer and have the same condition as you for the color parameter. You will get a smooth transition when the selected value changes. However, you may need to also add boxShadow to have the same elevation effect as Card
AnimatedContainer(
duration: const Duration(milliseconds: 700),
curve: Curves.easeInOut,
decoration:BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black,
blurRadius: 5,
spreadRadius: 5,
offset: Offset(0, 2),
),
],
color: selected ? AppColors.primary : AppColors.primaryLight,
),
)
One way to do this would be an AnimatedContainer
return Card(
child: AnimatedContainer(
duration: const Duration(milliseconds: 1000),
height: 200,
width: 200,
color: selected ? Colors.red : Colors.blue,
child: FooWidget(),
),
)

flutter animation acceleration or speed change

how can we change the acceleration of the animation in duration or make some stops in it's duration?
for example scale a widget to 2x in 3 second than stop for a second than scale it for another 2x in 3 seconds.
AnimationController_anim1 = AnimationController(
vsync: this,
duration: Duration(milliseconds: 3000),
);
ScaleTransition(
scale: Tween(begin: 1.0, end: 2).animate(_anim1),
child: ClipRect(
clipBehavior: Clip.hardEdge,
child: OverflowBox(
maxHeight: 70,
maxWidth: 70,
child: Center(
child: Container(
decoration: BoxDecoration(
color: Colors.white38,
shape: BoxShape.circle,
),
),
),
),
),
)
You can use Curve class which provides a way to map the unit interval of animation to the desired unit interval that your want
for example, curves should implement a transform function whic are mapper that receives a time value in a range of 0,1 which indicates animations current time progress and you can return a value to indicate what should be the new progress of the animation for example you can say if time is greater than 0 then return time2 which speeds up your animation as 2x also note that you should are allowed to return value in the range of 0 to 1 so in this example, your should bound the time2 to be at most 1
Here is link to Curve class documentation :
https://api.flutter.dev/flutter/animation/Curve-class.html
also, there are a few ready to use curves in the Curves class that you can already use or look to the implementation of those to inspire :
https://api.flutter.dev/flutter/animation/Curves-class.html
as I searched around, I found the solution in two different ways, one is what Amir Hossein Mirzaei mentioned, which use Curve class, it is very powerful and flexible but it is a bit complicated and hard solution (beside being so powerful), but the second way is more handy which handled by TweenSequence as bellow :
1 - make an animation controller 2- make TweenSequence and add TweenSequenceItem for each step of animation 3- set it to widget
AnimationController _anim1 = AnimationController(
vsync: this,
duration: Duration(milliseconds: 8500),
//reverseDuration: Duration(milliseconds: 1000),
)..repeat(reverse: true);
Animation<double> _animation1 = TweenSequence(
<TweenSequenceItem<double>>[
TweenSequenceItem<double>(
tween: Tween<double>(begin: 1.0, end: 1.5),
weight: 23.5,
),
TweenSequenceItem<double>(
tween: ConstantTween<double>(1.5),
weight: 6.0,
),
TweenSequenceItem<double>(
tween: Tween<double>(begin: 1.5, end: 2.0),
weight: 23.5,
),
TweenSequenceItem<double>(
tween: ConstantTween<double>(2.0),
weight: 47.0,
),
],
).animate(_anim1);
ScaleTransition(
scale: _animation1,
child: ClipRect(
clipBehavior: Clip.hardEdge,
child: OverflowBox(
maxHeight: 70,
maxWidth: 70,
child: Center(
child: Container(
decoration: BoxDecoration(
color: Colors.white38,
shape: BoxShape.circle,
),
),
),
),
),
)

Flutter: How to make a custom animated Drop Down Menu?

I'm trying to make a custom drop-down menu in Flutter that is just a simple button that on tap shows a scrollable row of products. I've attached some images that better show what I'm referring to. I tried to use an IconButton and an AnimatedContainer but I can't seem to get it working. I was hoping someone would have a better idea on how to do something like this.
Here is my code so far by the way:
class ModelsDropdown extends StatefulWidget {
final List<Phone> phones;
ModelsDropdown({#required this.phones});
#override
_ModelsDropdownState createState() => _ModelsDropdownState();
}
class _ModelsDropdownState extends State<ModelsDropdown> {
bool _droppedDown;
#override
void initState() {
_droppedDown = false;
super.initState();
}
#override
Widget build(BuildContext context) {
return AnimatedContainer(
duration: Duration(milliseconds: 300),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100.0),
border: Border.all(width: 2.0)
),
width: 32.0,
height: 32.0,
child: Column(
children: [
IconButton(
padding: const EdgeInsets.only(right: 0.0),
icon: Icon(
_droppedDown ? Icons.expand_more : Icons.expand_less
),
color: Colors.black,
onPressed: () {
setState(() {
_droppedDown = !_droppedDown;
});
}
),
_droppedDown ?
Container(
width: MediaQuery.of(context).size.width,
height: 300.0,
color: Colors.orangeAccent,
) :
SizedBox.shrink()
],
),
);
}
}
With the container at the bottom, it doesn't even work. I get an overflow error. Any help is very much appreciated. Thanks a lot, everyone.
I Think you should Change The Below Container with an AnimatedCrossFade.
Animated Cross Fade Has Two Child First and Second ...
https://api.flutter.dev/flutter/widgets/AnimatedCrossFade-class.html
Dont set Height for Your Child ... its Works Perfectly...
AnimatedCrossFade(
duration: const Duration(seconds: 3),
firstChild: Container(), // When you don't want to show menu..
secondChild: menu,
crossFadeState: _first ? CrossFadeState.showFirst : CrossFadeState.showSecond,
)
with this method you don't need Animated Container at top ... remove that.(return Column)...
with Animated cross Fade You don't need to Know The Height of widget and its for works dynamic Heights
-------------- if You Want to use Your Code and Use Fixed Height ----------------
width: _droppedDown ? YourWidth : 32.0,
height: _droppedDown ? 300 : 32.0,

How to animate height of the container relative to its children content?

I want to animate the height property of the container (AnimatedContainer in code below), but I don't want to set hard numbers like this (height: _visible2 ? 160 : 40.9) because height of this container is otherwise relative to its children content (mainly Text)
AnimatedContainer(
curve: Curves.ease,
height: _visible2 ? 160 : 40.9,
duration: Duration(milliseconds: 350),
child: AnimatedOpacity(
duration: Duration(milliseconds: 400),
opacity: _visible2 ? 1.0 : 0,
child: GestureDetector(
onTap: () {
_visible2
? setState(() {
_visible2 = !_visible2;
})
: null;
},
child: myWidget
),
),
)
Is there a way to animate from zero to relative height (for example height of this container can change in landscape mode due to more room for text to lay itself on the screen) ?

How to really use SizeTransition in Flutter?

I want to make the same effect as this: https://api.flutter.dev/flutter/widgets/SizeTransition-class.html but starting from the beginning of an image. I tried everything and this does not work!
I tried to put Align in it, to put a container with the width modified by the value of the animation.. nothing works!
I have an animation before, and then it will call forward() on this one when it finishes (there is a function called complete that calls the forward() function).
initState() {
_sizeController =
AnimationController(duration: Duration(seconds: 1), vsync: this)
..addListener(() {
setState(() {});
});
_sizeAnimation = Tween(begin: 0.0, end: 27.0).animate(CurvedAnimation(
parent: _sizeController, curve: Curves.fastLinearToSlowEaseIn));
}
AnimatedContainer(
width: _width,
height: _height,
duration: Duration(milliseconds: 200),
decoration: BoxDecoration(
color: _color,
border: Border.all(
color: Color(0xFF707070), width: 2, style: BorderStyle.solid),
borderRadius: BorderRadius.circular(14.0),
),
child: SizeTransition(
sizeFactor: _sizeAnimation,
axis: Axis.horizontal,
axisAlignment: -1,
child:
Center(child: Image.asset('assets/images/check.png')),
),
Or it does nothing or it animates by scaling only.. How can i achieve the same effect as the example video on the widget page? I want that effect to happen showing a checkmark image inside a circle container. And before this the animatedcontainer will be a linear container that turns into the circle, and then the checkmark appears.
you need to call _sizeController.forward() to run the animation