Flutter Animation Tutorial #6 - Animation Controllers

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay then gang so up until now flutter has taken care of a lot of the heavy lifting of all of our animations for us under the hood because we've been using implicit animations and built-in widgets and now i want to take more control of our animations by creating explicit animations and using what's known as animation controllers now animation controllers give us more granular of fine control over our animations and they're better suited to more complex animations or any kind of animation that flutter doesn't provide an out-of-the-box solution for so we're going to be using an animation controller to create our pulsating heart animation over here so what i'd like to happen is that when we click on the heart i want to animate the color from gray to red and then back from red to gray when i click on it again a bit like we're favoriting and unfavoriting this trip all right but i also want to do a little pulsating animation of the heart so it grows and then shrinks every time we click the icon too so we're gonna use an animation controller to control all of this so i need to open up the heart widget right here this is the widget that we're going to be animating and we can see at the minute all this is is an icon button and inside that we have an icon which is a favorite and a favorite looks like a little heart like this and we have a color which is a light gray and also a size of 30 pixels so these are the two different things we're going to be animating the color from grey to red and the size from 30 to maybe 50 back down to 30. we also have this unpressed handler right here which we will hook up later on the first thing i want to do though is create an animation controller so inside this state object right here i'm going to do that so this is going to be of type animation controller and i'm going to give this a name i'm just going to call it controller you can call it what you want all right so we have that variable right there but we're not setting it equal to a value yet and we'll do that inside init state so inside this we can update the value of this to be a new animation controller so i'm going to say controller is equal to animation controller like so okay so inside this animation controller we need to specify a couple of things first of all a duration so you know when we used built-in widgets and builders down here we specified the duration inside those widgets themselves but this time our controller is going to be controlling the animation and so now we specify the duration inside this animation controller so duration is going to be a duration object whereby the length of time is going to be in milliseconds for me and i'm going to set that equal to 200 because i want this to be quite a quick transition when it goes from gray to red if we make it too long it's going to look unnatural okay so we have the duration we also need a second property and that is a v sync property now if we hover over this v-sync we can see that this needs to be a ticker provider now a ticker is a bit like a clock that ticks for our animation over and over so that for every tick we get a new animation value from point a to b so the vsync property allows us to sync this controller that we have right here with a ticker now the ticker we sync it with will be our stateful widget itself right here so then only when this widget tree is active on a screen will the animation tick now to allow our widget to act as a ticker we need to use a mixing up here so we're going to use the single ticker provider state mixing so i'm going to say with single ticker provider state mixing and now this widget right here has the ability to act as a ticker so now i can sync this controller with this to be its ticker and to do that i can just say this to reference this class itself all right so again vsync right here syncs our controller with an animation ticker we give our widget the ability to be a ticker provider therefore it's only going to be working while the current widget is in play on the screen so now we have a basic animation controller to control the animation so we can therefore play the animation by using this controller now to do that we use the forward method on the controller itself so i could say down here controller dot forward and that will start the animation controller for us now automatically the animation controller is going to spit out values from zero to one so the default tween essentially is from zero to one now we can listen for whatever value it spits out when it does spit out a new value by adding a listener to the controller so to do that we can come down here and say controller dot add listener and inside here we can pass a function which is gonna fire every time this controller emits a new value and it's emitting values between 0 and 1 over this time period 200 milliseconds so let me just inside this listener print out the value of the controller so i'm going to say prints and then we can access the controller and we get a property called value so that's the value it's spitting out over this time duration so now if i save this and open up the terminal and go to the debug console what i'm going to do is restart this over here and we should see these values over here in the console first of all though we need to go to the details component which is where the heart is so let me click on one of those and now we can see these different values over time okay so we have these four different values and essentially we could use those values now to animate certain things down here now at the minute we just want to animate the color first of all so this zero to one isn't going to be of much help so really we need a color tween instead of the default mean from zero to one so then instead of this spitting out values from zero to one we want to create a tween which is going to give us values transitioning from one color gray to another which is going to be red so to do that we'll need to make a color tween and a color animation so let me go to the top here i'm going to create first of all a new animation object and i'm going to call this color animation now what we can do is create a tween that is going to be linked to this color animation so down here i'm going to after the controller create a color animation and i'm going to say color animation is equal to a color tween first of all and in here we're going to say where we want to go from and to by using begin and setting that equal to colors dot gray and it's going to be 400 so that's the current state of it right here okay that's the initial beginning color and then we're going to end at colors dot red and that's all there is to it now there's an error at the minute because this is a tween and we're trying to set it equal to an animation object right so a tween isn't an animation object but what we can now do with this tween is called the animate method on it by saying dot animate and inside this animate method we pass through the controller that we want to control this animation well that's this thing right here so i can say now the controller is controlling this animation and now we no longer get that error because this does return an animation for us so basically all we're doing is creating a tween and telling this controller to control that tween animation all right so now when we listen to values on this animation then we're gonna get values between the gray color and the red color instead of between 0 and 1. now the controller value is still going to be 0 to 1 because we're not actually changing the controller we're just creating a new animation with a tween for colors and then we're telling our controller to control that so it uses this duration it uses this ticker but this time this will emit values which are colors and not zero to one so we can still access this on the controller itself but now also we can access values on this as well the same way and again every time it spits out a new value between this color and this color then this function is gonna fire and we can listen for that new value so let me now say i want to print color animation dot value and now we should see the numbers zero to one but also the colors down in the console as well so let me open that up and go to debug console then i'm gonna restart the process over here and i'm gonna go into one of these screens and now we can see we get these colors as well coming from the color tween as well as just the numbers all right so now we could potentially use this value right here color animation dot value down here to animate the color so then let's try this let's instead of hard coding this color output this changing value right here the color animation value so let me copy that and paste it right here and i'm going to save this and then i'm going to restart the process and then i'm going to click on one of these and well it doesn't change value and that is true for any of these so why is this not working because we're telling our animation to start and we're changing the values and we can see those changing values down here so why is it not updating inside the build method well remember the build method is not going to automatically re-run and re-render the different color every time this value changes it's only going to be triggered to re-run if we use set state so potentially what we could do is use set state inside here and that is going to re-trigger the build function let me just put a semicolon at the end if i say this it's going to retrigger the build function every time the value changes and therefore it's going to update over here so if i go over here and you can see now it's red right so it's animated very quickly to red even really before it fully loads the screen now the other option instead of using that would be to use something called an animated builder so the animated builder is a widget that would surround this thing right here that we're trying to animate now it will actively listen for changes in our animation controller and then rebuild the tree automatically when there is a change so we wouldn't need to worry about using set state so we're going to use animated builder instead to flesh out this animation so let me first of all take this widget and i'm going to go to the context menu and wrap with a new widget and this is animated builder like so okay so inside this animated builder we need an animation property first of all and this animation is going to be the controller right here so let me grab that and let me paste in right here now the second thing we need is a builder so i'm going to say builder and that is a function where we take in the build context which is the context object we have right here and we can also take in a second argument which would be a widget and that could be this child right here but i'm not going to do that i'm not going to use that because this is actually the thing we want to animate so i'm going to instead return all of this stuff right here the icon button inside here and i can get rid then of the child like so and place a semicolon right there let me just now scoot this in a little bit okay that looks a bit better so now every time the controller value changes then we're gonna rebuild this thing right here and therefore it's going to output the new value every time it changes so if i save this and go back and in fact let's restart the whole process to make sure all the changes were caught and then if i go to one of these we can see it animates the red straight away now at the minute that's not much of an animation because it just happens automatically very very quickly 200 milliseconds now in actual fact i don't want it to be red straight away i only want it to animate to red when we click on it so instead of using controller.forward right here let's cut it from there so it's not automatic and instead place it inside this on pressed handler so now only when we press the initial gray heart is the animation going to start so if i save that now and restart this process so we go back to the initial state then click on one of these then it starts as great if i click on this it animates to red very quickly now that is a very very quick animation so let's change this to something like 500 instead and then if i go back and in fact we'll restart the process and click on one of these things and if i click on this now you can see it's a slightly slower animation okay so now we've used an animation controller to animate the color of this heart when we click on it now ideally when we click on it again i want to unfavorite it so animate it back from red to gray and to do that we'll need to reverse the animation okay then so we need to figure out how to reverse this animation once we click on it again well to do that we're going to have to listen to the status of the animation is the animation complete well if it is we can do something maybe to reverse that animation is it in its initial state well if it is we can take the animation forward again all right so we need to somehow listen for the status of the animation now to do that we can add a status listener to the controller so a bit like we've added a listener right here which fires a function every time the value changes from a controller we can also add a status listener to the controller which listens for the status of the controller and it's going to run a function every time that changes so when the animation is complete it will run a function if the status changes back to its initial state then it will run the function so let me add this down here i'm going to paste it in so we take the controller and we add a status listener so this is just add listener for the value this is a status listener for the actual status of the controller now in here i'm going to fire a callback function when the status changes and take in that status so i'm going to open this up and place my closing parenthesis at the end and inside here all i'm going to do for now is print out the status so we can see that as it changes so let me save this and let me now restart the process and go to the debug console right over here so now if we click on this we can see at the bottom we get animation status completed so at this point we know that the animation is complete now there is also another animation status called dismissed and that means we've gone back to the beginning and it's dismissed again right so if we were to run for example a different method instead of forward down here i'm going to change this to reverse then it will go back from this state to the initial state again and at that point we're gonna get animation status dismissed so if i now come over here and press this we can see at the bottom it's gone back to gray now because we reversed the animation and now we get dismissed okay so what we could potentially do is listen for these different statuses right here and the minute we reach the completed status we could update a boolean that we use to be true to say look it's currently favorited right and at that point if that boolean is true instead of running forward down here we run reverse right and that's going to reverse the animation now in here as well we could also check whether the status is dismissed and at that point we can then change the boolean to false to say no it currently isn't favorited anymore and if it's false down here in the unpressed handler we can then forward the animation i hope that makes sense so let's flesh this out i'm going to get rid of this print statement right here and i'm just going to paste in a couple of if checks so you don't have to watch me type them all out and right here we say if the status is equal to animation status dot completed then i want to update the state and i'm going to take this value which we've not created yet and set it equal to true that means we've favorited it because we've completed the animation and it's red so now this is favorited if the animation status however is dismissed then we're going to update the state and set his favorite to false to say look actually we've just unfavorited that it's gray again and this is not a favorite all right so now we need to create this value up here so above animation controller i'll create this value and this is going to be a boolean so we need to say bool and it was called is fave and we're going to set that equal to false to begin with because the initial state of something is going to be false it's not going to be favorited automatically when we come onto the screen ultimately this could be controlled by user information in a database or something but for us we're just going to start off as false okay so we're now updating that dependent on the animation status if it's complete we set it to true because now it's red and favorited if it's dismissed then it's going to be false because it's not a favorite anymore so now we can use this boolean to either say forward or reversed right if it's true that means it's currently read and favorited at that point when we click it we want to reverse the animation if it's false it means it's not favorited it's gray and we want to forward the animation so it goes red so now here let me cut this and instead we're going to use a ternary operator to control this so i'm going to evaluate is fave right question mark so this is going to be true or false now if it's true we're going to do something here and if it's false on the other side of the colon we do something here right now the thing we want to do if it's false is say control up forward because if it's not a favorite we want to animate it to red and make it a favorite right and the thing to do if it's true well we need to reverse that to make it not a favorite again so i'm going to say controller dot reverse right here instead and that's all there is to it so if i save this now and restart over here the whole process fingers crossed this should all work if i click on one of these and then click it it goes red if i click it again it should go gray again red gray okay and that's all controlled via this boolean these two methods and this status listener right here so there is one last thing to do we need to dispose of the animation controller in the dispose method inside this widget and this removes the controller when the widget leaves the screen and it makes sure it doesn't continue to eat up resources in the background when we're not using him so to do that we need to come below the init method and we need to use the dispose hook instead and instead of that we need to dispose of the animation controller so let's say controller dot dispose and that gets rid of it for us and that's all there is to it so let's just restart this make sure everything still works on all of these different details pages so yep that works and if i go to a different one yep works these are all working so next up we're going to look at how to grow and shrink the heart like a pulse effect when we click on it
Info
Channel: Net Ninja
Views: 41,378
Rating: undefined out of 5
Keywords: flutter, flutter tutorial, flutter animations, flutter animation, flutter animations tutorial, tutorial, animation, app animation, flutter animation tutorial, animation tutorial, flutter custom animations, animation controller, controller, animationController, animation builder, animated builder, flutter animation controller
Id: k5BDKI7R6ag
Channel Id: undefined
Length: 21min 28sec (1288 seconds)
Published: Thu Aug 06 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.