Build a drag & drop 🖖 UI in the form of a simple color-matching kid's game. Master the basics of Flutter's Draggable and DragTarget widgets https://fireship.io/lessons/flutter-drag-and-drop-basics/


- Draggable https://docs.flutter.io/flutter/widgets/Draggable-class.html
- DragTarget https://docs.flutter.io/flutter/widgets/DragTarget-class.html

#flutter
2024-02-04T06:47:42.043Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
ed00a605-c4b5-4ed6-8da5-929a68bcb48c
c02a43b512bd1fdfe14636cff3906d150047a6bfae16693bbae4e282eb4da77c
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Yesterday, my 2 year old was playing with a book that has you connect a color to a fruit.
And I realized that would be the perfect feature to demonstrate drag and drop and flutter.
In today's video, we'll build a simple kids game that allows you to drag a fruit over to a square with the corresponding color.
If you drop it on the correct square, it will update the score and also give you some audio feedback.
If you're new here, like and subscribe and you can find the full source code on Fireship IO.
Now, before we get started, a lot of people have asked me when I'm going to release a full Flutter course.
The answer is very soon.
It'll be released before Google IO, which is now only 6 days away, So expect more details on that in the next few days.
Now, let's go ahead and take a closer look at the app we're building today.
You'll see 2 columns here and you can grab an item from the column on the left and then drag it to a target on the right.
If it's the correct color, it will mark it as correct and then update the score, but if it's dropped on the incorrect target, then it will just go back to its original position.
And then we'll also randomize the ordering of the targets for each round just so there's a little bit of replay value.
And as an added touch, we'll play a little sound effect every time the user makes a successful drop.
If we jump into the code, the first thing we'll look at is the pubspec.
Yaml file.
The only dependency outside of Flutter is this audio players plug in.
I really like this plugin because it works on both iOS and Android and also allows you to play multiple audio files simultaneously, and that tends to be pretty important if you're building a game.
And you'll also notice that we have an MP 3 file here registered in the assets directory, and I've also registered a custom font called Press Start, which you can download from Google Fonts that'll give you that kind pixelated retro look.
Now moving on to the source code, I'm importing dart math as well as the audio players plug in.
Then we'll update the font family and our theme data, and then we'll set the homepage as this color game screen that we're about to define now.
The screen itself is a stateful widget, and the first property we'll define is the score, which just starts out as an empty map.
Eventually, we'll update the keys on this map when the user drags a draggable widget onto the correct drag target.
The next thing we'll define is a map of choices, and so each emoji, which is a string, will map to a material color.
Emojis are really handy because they not only provide a graphic that we can use for the UI, but we can also use them to organize the game logic itself.
For example, if the user correctly drags to the green square, then we can update the score with the corresponding emoji key.
We'll We'll also define an integer here called seed, which will be used as a random seed to shuffle the order of the items as we loop over them.
And then we'll use the audio cache class to play a local m p 3 file, and we'll call that our audio controller.
From there, we'll set up a scaffold, and in the app bar for that scaffold, we'll display the score, And then we'll have a floating action button that allows the user to reset the game.
We can display the score by setting up a text widget, and then to calculate the score, all we have to do is look at the length of that score map.
And you can use the dollar sign brackets to interpolate an expression directly inside of a string and dart.
Now the purpose of the floating action button is to reset the game.
So in order to do that, we'll call set state, and then we'll clear out all of the key value pairs inside of that score map.
And we also want to add some randomness after each game, so we'll increment our random seed by 1.
That takes care of the outer UI.
Now we'll set up a row that has 2 columns laid out side by side, the draggable stuff on the left with the drop targets on the right.
So the first column in the row will take care of the draggable widgets, and we'll want each of our 6 choices to be a draggable widget.
So we'll go ahead and loop over the keys in the map.
And if you remember from earlier, each key in that map is just an emoji string.
Now we're ready to start using Flutter's draggable widget, which allows the user to drag a child widget around the screen.
Now there are 3 different things you might wanna display with a draggable widget.
The first one is just the default child, which is what will be displayed when the user is not interacting with it.
When the user starts to drag, that will open the door to 2 additional UI elements.
The initial child disappears and then we have this feedback widget, which is what is actually being dragged around the screen.
And then we also have the option to define a child when dragging widget which will be displayed to replace the original child when it's being dragged.
Now getting back to our code, there's one important thing I want to point out here and that's that if you're passing data from a draggable widget to a drop target, you should provide it with a generic type that represents the data that you're passing to the drop target, which in our case is just a string.
Then to actually pass the data, we'll go ahead and define the data property as our emoji.
Now at this point, we're ready to define the 3 different widgets which include, again, the child, the feedback, and the child when dragging.
Now depending on your UI, this may be a good opportunity to refactor your code into a different widget.
In our case here, all 3 of these widgets are very similar, so we'll go ahead and define a new stateless widget called emoji that takes a string emoji as an input.
Then down here in the build method, I'll start by defining a material widget.
And the reason I'm starting with this material widget is because for whatever reason, the draggable feedback doesn't seem to want to inherit the text styles from the main app.
And then the rest of it is just very basic Flutter stuff like a container that's aligned to the center that has a specific height and width.
But because we extracted this logic into its own stateless widget, we can now reuse it 3 times up in the draggable widget in a very dry and maintainable way.
So we can use our emoji widget up here as the child, and when passing in the actual emoji argument, we'll go ahead and check to see if that one's already been answered correctly.
If it's been answered Correctly, we'll just display a check mark.
Otherwise, we'll display the emoji itself.
For the feedback widget, we'll always just want to display the emoji, but you might want to add some box shadow or maybe make it larger here to give it the effect of being grabbed.
And, lastly, we can use the emoji widget as the child when dragging property as well.
And that's all it takes to build a draggable widget, and there's also a number of different callbacks that you can listen to on draggable to handle different UI interactions based on the state of what's being dragged.
But in many cases, you want to drag something to a specific location and have it interact with a different widget, which we can do with a drop target.
In our case, we're going to build multiple drop targets, and each one of those targets corresponds to a specific emoji that is allowed to be dropped on top of it.
We'll go ahead and loop over the keys in the choices map again, but this time I'm going to define a function called build drag target that will build the widgets for each individual drop zone.
Then I'm going to call dot dot shuffle with our random seed, and that will randomize the order of the items in this list.
The two dots here are called cascade Cade notation in Dart, and they allow you to make a sequence of operations on the same object.
In this case, shuffle doesn't actually return the array.
It just mutates the original.
So So without the cascade notation, we'd have to create a temporary variable just to shuffle the array which would take a few more lines of code.
That's just one of the many ways that Dart makes life a little bit easier for you.
Now we're ready to define the actual drag target, and we wanna make sure to pass in the generic string type here for the data type that we're dropping on top of this target.
The next thing we'll do is define its builder function, which gives us access to the build context, a list of accepted data, and a list of rejected data.
We can use that data to determine how the UI should look for the drag target.
Now, in our case, we're keeping track of the score on the parent stateful widget, which means we can just look at the score map for this particular emoji to determine which UI elements to show.
If the users already answered this one Then we'll just display a white container that has the text of correct.
But if the user has not answered this one correctly, then we'll go ahead and display a container that has the corresponding color to that emoji.
And again, that data is contained in the choices map, which we defined at the beginning of the video.
But how do we know whether or not a user has Will they drop something on the drag target, and whether or not that's valid data to be dropped there in the first place?
We can decide if the data is valid or not by defining this on will accept function.
This will fire when the user drags something on top of the target.
So in our case, we can look at the data or the emoji string and make sure that it matches the emoji of this particular widget.
In other words, you should only be able to drop the tomato on the red drop zone.
That'll fire when the user first hovers over the drag target.
But when they actually drop the item and it's accepted, it will fire this on accept function.
And we also have on leave if it's dropped and it's not accepted or if they just leave the drop zone altogether.
When the user makes a successful drop, we'll go ahead and call set state and update the score on the stateful widget.
In addition, we can also play a sound here, which we can easily do with our audio controller by calling play and then passing it the name of our MP 3 file.
And that's all there is to it.
We now have a fully functional drag and drop UI, and I think the only possible way to make it better would be to add in some annoying mobile ads, But we'll save that for another episode.
I'm gonna go ahead and wrap things up there.
If this video helped you, please like and subscribe and consider becoming a pro member at Fireship IO to get access to the Upcoming Flutter course.
Thanks for watching, and I will talk to you soon.
I choose chunky style build because it has the wholesome chunks growing kids need.

Speaker 0: Yesterday, my 2 year old was playing with a book that has you connect a color to a fruit. And I realized that would be the perfect feature to demonstrate drag and drop and flutter. In today's video, we'll build a simple kids game that allows you to drag a fruit over to a square with the corresponding color. If you drop it on the correct square, it will update the score and also give you some audio feedback. If you're new here, like and subscribe and you can find the full source code on Fireship IO.

Now, before we get started, a lot of people have asked me when I'm going to release a full Flutter course. The answer is very soon. It'll be released before Google IO, which is now only 6 days away, So expect more details on that in the next few days. Now, let's go ahead and take a closer look at the app we're building today. You'll see 2 columns here and you can grab an item from the column on the left and then drag it to a target on the right.

If it's the correct color, it will mark it as correct and then update the score, but if it's dropped on the incorrect target, then it will just go back to its original position. And then we'll also randomize the ordering of the targets for each round just so there's a little bit of replay value. And as an added touch, we'll play a little sound effect every time the user makes a successful drop. If we jump into the code, the first thing we'll look at is the pubspec. Yaml file.

The only dependency outside of Flutter is this audio players plug in. I really like this plugin because it works on both iOS and Android and also allows you to play multiple audio files simultaneously, and that tends to be pretty important if you're building a game. And you'll also notice that we have an MP 3 file here registered in the assets directory, and I've also registered a custom font called Press Start, which you can download from Google Fonts that'll give you that kind pixelated retro look. Now moving on to the source code, I'm importing dart math as well as the audio players plug in. Then we'll update the font family and our theme data, and then we'll set the homepage as this color game screen that we're about to define now.

The screen itself is a stateful widget, and the first property we'll define is the score, which just starts out as an empty map. Eventually, we'll update the keys on this map when the user drags a draggable widget onto the correct drag target. The next thing we'll define is a map of choices, and so each emoji, which is a string, will map to a material color. Emojis are really handy because they not only provide a graphic that we can use for the UI, but we can also use them to organize the game logic itself. For example, if the user correctly drags to the green square, then we can update the score with the corresponding emoji key.

We'll We'll also define an integer here called seed, which will be used as a random seed to shuffle the order of the items as we loop over them. And then we'll use the audio cache class to play a local m p 3 file, and we'll call that our audio controller. From there, we'll set up a scaffold, and in the app bar for that scaffold, we'll display the score, And then we'll have a floating action button that allows the user to reset the game. We can display the score by setting up a text widget, and then to calculate the score, all we have to do is look at the length of that score map. And you can use the dollar sign brackets to interpolate an expression directly inside of a string and dart.

Now the purpose of the floating action button is to reset the game. So in order to do that, we'll call set state, and then we'll clear out all of the key value pairs inside of that score map. And we also want to add some randomness after each game, so we'll increment our random seed by 1. That takes care of the outer UI. Now we'll set up a row that has 2 columns laid out side by side, the draggable stuff on the left with the drop targets on the right.

So the first column in the row will take care of the draggable widgets, and we'll want each of our 6 choices to be a draggable widget. So we'll go ahead and loop over the keys in the map. And if you remember from earlier, each key in that map is just an emoji string. Now we're ready to start using Flutter's draggable widget, which allows the user to drag a child widget around the screen. Now there are 3 different things you might wanna display with a draggable widget.

The first one is just the default child, which is what will be displayed when the user is not interacting with it. When the user starts to drag, that will open the door to 2 additional UI elements. The initial child disappears and then we have this feedback widget, which is what is actually being dragged around the screen. And then we also have the option to define a child when dragging widget which will be displayed to replace the original child when it's being dragged. Now getting back to our code, there's one important thing I want to point out here and that's that if you're passing data from a draggable widget to a drop target, you should provide it with a generic type that represents the data that you're passing to the drop target, which in our case is just a string.

Then to actually pass the data, we'll go ahead and define the data property as our emoji. Now at this point, we're ready to define the 3 different widgets which include, again, the child, the feedback, and the child when dragging. Now depending on your UI, this may be a good opportunity to refactor your code into a different widget. In our case here, all 3 of these widgets are very similar, so we'll go ahead and define a new stateless widget called emoji that takes a string emoji as an input. Then down here in the build method, I'll start by defining a material widget.

And the reason I'm starting with this material widget is because for whatever reason, the draggable feedback doesn't seem to want to inherit the text styles from the main app. And then the rest of it is just very basic Flutter stuff like a container that's aligned to the center that has a specific height and width. But because we extracted this logic into its own stateless widget, we can now reuse it 3 times up in the draggable widget in a very dry and maintainable way. So we can use our emoji widget up here as the child, and when passing in the actual emoji argument, we'll go ahead and check to see if that one's already been answered correctly. If it's been answered Correctly, we'll just display a check mark.

Otherwise, we'll display the emoji itself. For the feedback widget, we'll always just want to display the emoji, but you might want to add some box shadow or maybe make it larger here to give it the effect of being grabbed. And, lastly, we can use the emoji widget as the child when dragging property as well. And that's all it takes to build a draggable widget, and there's also a number of different callbacks that you can listen to on draggable to handle different UI interactions based on the state of what's being dragged. But in many cases, you want to drag something to a specific location and have it interact with a different widget, which we can do with a drop target.

In our case, we're going to build multiple drop targets, and each one of those targets corresponds to a specific emoji that is allowed to be dropped on top of it. We'll go ahead and loop over the keys in the choices map again, but this time I'm going to define a function called build drag target that will build the widgets for each individual drop zone. Then I'm going to call dot dot shuffle with our random seed, and that will randomize the order of the items in this list. The two dots here are called cascade Cade notation in Dart, and they allow you to make a sequence of operations on the same object. In this case, shuffle doesn't actually return the array.

It just mutates the original. So So without the cascade notation, we'd have to create a temporary variable just to shuffle the array which would take a few more lines of code. That's just one of the many ways that Dart makes life a little bit easier for you. Now we're ready to define the actual drag target, and we wanna make sure to pass in the generic string type here for the data type that we're dropping on top of this target. The next thing we'll do is define its builder function, which gives us access to the build context, a list of accepted data, and a list of rejected data.

We can use that data to determine how the UI should look for the drag target. Now, in our case, we're keeping track of the score on the parent stateful widget, which means we can just look at the score map for this particular emoji to determine which UI elements to show. If the users already answered this one Then we'll just display a white container that has the text of correct. But if the user has not answered this one correctly, then we'll go ahead and display a container that has the corresponding color to that emoji. And again, that data is contained in the choices map, which we defined at the beginning of the video.

But how do we know whether or not a user has Will they drop something on the drag target, and whether or not that's valid data to be dropped there in the first place? We can decide if the data is valid or not by defining this on will accept function. This will fire when the user drags something on top of the target. So in our case, we can look at the data or the emoji string and make sure that it matches the emoji of this particular widget. In other words, you should only be able to drop the tomato on the red drop zone.

That'll fire when the user first hovers over the drag target. But when they actually drop the item and it's accepted, it will fire this on accept function. And we also have on leave if it's dropped and it's not accepted or if they just leave the drop zone altogether. When the user makes a successful drop, we'll go ahead and call set state and update the score on the stateful widget. In addition, we can also play a sound here, which we can easily do with our audio controller by calling play and then passing it the name of our MP 3 file.

And that's all there is to it. We now have a fully functional drag and drop UI, and I think the only possible way to make it better would be to add in some annoying mobile ads, But we'll save that for another episode. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe and consider becoming a pro member at Fireship IO to get access to the Upcoming Flutter course. Thanks for watching, and I will talk to you soon.

I choose chunky style build because it has the wholesome chunks growing kids need.
Yesterday, my 2 year old was playing with a book that has you connect a color to a fruit. And I realized that would be the perfect feature to demonstrate drag and drop and flutter. In today's video, we'll build a simple kids game that allows you to drag a fruit over to a square with the corresponding color. If you drop it on the correct square, it will update the score and also give you some audio feedback. If you're new here, like and subscribe and you can find the full source code on Fireship IO.
fruits
games
video gaming
toys
Now, before we get started, a lot of people have asked me when I'm going to release a full Flutter course.
The answer is very soon. It'll be released before Google IO, which is now only 6 days away, So expect more details on that in the next few days. Now, let's go ahead and take a closer look at the app we're building today. You'll see 2 columns here and you can grab an item from the column on the left and then drag it to a target on the right.
google
If it's the correct color, it will mark it as correct and then update the score, but if it's dropped on the incorrect target, then it will just go back to its original position.
And then we'll also randomize the ordering of the targets for each round just so there's a little bit of replay value. And as an added touch, we'll play a little sound effect every time the user makes a successful drop. If we jump into the code, the first thing we'll look at is the pubspec. Yaml file. The only dependency outside of Flutter is this audio players plug in. I really like this plugin because it works on both iOS and Android and also allows you to play multiple audio files simultaneously, and that tends to be pretty important if you're building a game. And you'll also notice that we have an MP 3 file here registered in the assets directory, and I've also registered a custom font called Press Start, which you can download from Google Fonts that'll give you that kind pixelated retro look.
video gaming
youtube
games
software
streaming
software development
gambling
Now moving on to the source code, I'm importing dart math as well as the audio players plug in. Then we'll update the font family and our theme data, and then we'll set the homepage as this color game screen that we're about to define now. The screen itself is a stateful widget, and the first property we'll define is the score, which just starts out as an empty map. Eventually, we'll update the keys on this map when the user drags a draggable widget onto the correct drag target. The next thing we'll define is a map of choices, and so each emoji, which is a string, will map to a material color. Emojis are really handy because they not only provide a graphic that we can use for the UI, but we can also use them to organize the game logic itself. For example, if the user correctly drags to the green square, then we can update the score with the corresponding emoji key. We'll We'll also define an integer here called seed, which will be used as a random seed to shuffle the order of the items as we loop over them. And then we'll use the audio cache class to play a local m p 3 file, and we'll call that our audio controller. From there, we'll set up a scaffold, and in the app bar for that scaffold, we'll display the score, And then we'll have a floating action button that allows the user to reset the game.
video gaming
visualization
animation
games
graphic design
machine learning
toys
We can display the score by setting up a text widget, and then to calculate the score, all we have to do is look at the length of that score map.
And you can use the dollar sign brackets to interpolate an expression directly inside of a string and dart. Now the purpose of the floating action button is to reset the game. So in order to do that, we'll call set state, and then we'll clear out all of the key value pairs inside of that score map.
gambling
games
And we also want to add some randomness after each game, so we'll increment our random seed by 1. That takes care of the outer UI. Now we'll set up a row that has 2 columns laid out side by side, the draggable stuff on the left with the drop targets on the right.
games
So the first column in the row will take care of the draggable widgets, and we'll want each of our 6 choices to be a draggable widget.
So we'll go ahead and loop over the keys in the map. And if you remember from earlier, each key in that map is just an emoji string. Now we're ready to start using Flutter's draggable widget, which allows the user to drag a child widget around the screen. Now there are 3 different things you might wanna display with a draggable widget. The first one is just the default child, which is what will be displayed when the user is not interacting with it. When the user starts to drag, that will open the door to 2 additional UI elements. The initial child disappears and then we have this feedback widget, which is what is actually being dragged around the screen.
animation
infants
And then we also have the option to define a child when dragging widget which will be displayed to replace the original child when it's being dragged.
Now getting back to our code, there's one important thing I want to point out here and that's that if you're passing data from a draggable widget to a drop target, you should provide it with a generic type that represents the data that you're passing to the drop target, which in our case is just a string. Then to actually pass the data, we'll go ahead and define the data property as our emoji. Now at this point, we're ready to define the 3 different widgets which include, again, the child, the feedback, and the child when dragging. Now depending on your UI, this may be a good opportunity to refactor your code into a different widget.
phones
data
In our case here, all 3 of these widgets are very similar, so we'll go ahead and define a new stateless widget called emoji that takes a string emoji as an input.
Then down here in the build method, I'll start by defining a material widget. And the reason I'm starting with this material widget is because for whatever reason, the draggable feedback doesn't seem to want to inherit the text styles from the main app. And then the rest of it is just very basic Flutter stuff like a container that's aligned to the center that has a specific height and width. But because we extracted this logic into its own stateless widget, we can now reuse it 3 times up in the draggable widget in a very dry and maintainable way.
graphic design
animation
So we can use our emoji widget up here as the child, and when passing in the actual emoji argument, we'll go ahead and check to see if that one's already been answered correctly. If it's been answered Correctly, we'll just display a check mark. Otherwise, we'll display the emoji itself. For the feedback widget, we'll always just want to display the emoji, but you might want to add some box shadow or maybe make it larger here to give it the effect of being grabbed.
And, lastly, we can use the emoji widget as the child when dragging property as well. And that's all it takes to build a draggable widget, and there's also a number of different callbacks that you can listen to on draggable to handle different UI interactions based on the state of what's being dragged.
animation
toys
But in many cases, you want to drag something to a specific location and have it interact with a different widget, which we can do with a drop target. In our case, we're going to build multiple drop targets, and each one of those targets corresponds to a specific emoji that is allowed to be dropped on top of it. We'll go ahead and loop over the keys in the choices map again, but this time I'm going to define a function called build drag target that will build the widgets for each individual drop zone. Then I'm going to call dot dot shuffle with our random seed, and that will randomize the order of the items in this list. The two dots here are called cascade Cade notation in Dart, and they allow you to make a sequence of operations on the same object. In this case, shuffle doesn't actually return the array. It just mutates the original. So So without the cascade notation, we'd have to create a temporary variable just to shuffle the array which would take a few more lines of code. That's just one of the many ways that Dart makes life a little bit easier for you. Now we're ready to define the actual drag target, and we wanna make sure to pass in the generic string type here for the data type that we're dropping on top of this target.
The next thing we'll do is define its builder function, which gives us access to the build context, a list of accepted data, and a list of rejected data. We can use that data to determine how the UI should look for the drag target. Now, in our case, we're keeping track of the score on the parent stateful widget, which means we can just look at the score map for this particular emoji to determine which UI elements to show.
visualization
machine learning
programming
If the users already answered this one Then we'll just display a white container that has the text of correct. But if the user has not answered this one correctly, then we'll go ahead and display a container that has the corresponding color to that emoji.
And again, that data is contained in the choices map, which we defined at the beginning of the video. But how do we know whether or not a user has Will they drop something on the drag target, and whether or not that's valid data to be dropped there in the first place? We can decide if the data is valid or not by defining this on will accept function. This will fire when the user drags something on top of the target. So in our case, we can look at the data or the emoji string and make sure that it matches the emoji of this particular widget.
data
In other words, you should only be able to drop the tomato on the red drop zone. That'll fire when the user first hovers over the drag target. But when they actually drop the item and it's accepted, it will fire this on accept function. And we also have on leave if it's dropped and it's not accepted or if they just leave the drop zone altogether.
When the user makes a successful drop, we'll go ahead and call set state and update the score on the stateful widget. In addition, we can also play a sound here, which we can easily do with our audio controller by calling play and then passing it the name of our MP 3 file.
audio
music
And that's all there is to it. We now have a fully functional drag and drop UI, and I think the only possible way to make it better would be to add in some annoying mobile ads, But we'll save that for another episode.
I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe and consider becoming a pro member at Fireship IO to get access to the Upcoming Flutter course. Thanks for watching, and I will talk to you soon. I choose chunky style build because it has the wholesome chunks growing kids need.
youtube
fashion
crafts
video gaming
Yesterday, my 2 year old was playing with a book that has you connect a color to a fruit. And I realized that would be the perfect feature to demonstrate drag and drop and flutter. In today's video, we'll build a simple kids game that allows you to drag a fruit over to a square with the corresponding color. If you drop it on the correct square, it will update the score and also give you some audio feedback. If you're new here, like and subscribe and you can find the full source code on Fireship IO. Now, before we get started, a lot of people have asked me when I'm going to release a full Flutter course. The answer is very soon. It'll be released before Google IO, which is now only 6 days away, So expect more details on that in the next few days. Now, let's go ahead and take a closer look at the app we're building today. You'll see 2 columns here and you can grab an item from the column on the left and then drag it to a target on the right. If it's the correct color, it will mark it as correct and then update the score, but if it's dropped on the incorrect target, then it will just go back to its original position. And then we'll also randomize the ordering of the targets for each round just so there's a little bit of replay value. And as an added touch, we'll play a little sound effect every time the user makes a successful drop. If we jump into the code, the first thing we'll look at is the pubspec. Yaml file. The only dependency outside of Flutter is this audio players plug in. I really like this plugin because it works on both iOS and Android and also allows you to play multiple audio files simultaneously, and that tends to be pretty important if you're building a game. And you'll also notice that we have an MP 3 file here registered in the assets directory, and I've also registered a custom font called Press Start, which you can download from Google Fonts that'll give you that kind pixelated retro look. Now moving on to the source code, I'm importing dart math as well as the audio players plug in. Then we'll update the font family and our theme data, and then we'll set the homepage as this color game screen that we're about to define now. The screen itself is a stateful widget, and the first property we'll define is the score, which just starts out as an empty map. Eventually, we'll update the keys on this map when the user drags a draggable widget onto the correct drag target. The next thing we'll define is a map of choices, and so each emoji, which is a string, will map to a material color. Emojis are really handy because they not only provide a graphic that we can use for the UI, but we can also use them to organize the game logic itself. For example, if the user correctly drags to the green square, then we can update the score with the corresponding emoji key. We'll We'll also define an integer here called seed, which will be used as a random seed to shuffle the order of the items as we loop over them. And then we'll use the audio cache class to play a local m p 3 file, and we'll call that our audio controller. From there, we'll set up a scaffold, and in the app bar for that scaffold, we'll display the score, And then we'll have a floating action button that allows the user to reset the game. We can display the score by setting up a text widget, and then to calculate the score, all we have to do is look at the length of that score map. And you can use the dollar sign brackets to interpolate an expression directly inside of a string and dart. Now the purpose of the floating action button is to reset the game. So in order to do that, we'll call set state, and then we'll clear out all of the key value pairs inside of that score map. And we also want to add some randomness after each game, so we'll increment our random seed by 1. That takes care of the outer UI. Now we'll set up a row that has 2 columns laid out side by side, the draggable stuff on the left with the drop targets on the right. So the first column in the row will take care of the draggable widgets, and we'll want each of our 6 choices to be a draggable widget. So we'll go ahead and loop over the keys in the map. And if you remember from earlier, each key in that map is just an emoji string. Now we're ready to start using Flutter's draggable widget, which allows the user to drag a child widget around the screen. Now there are 3 different things you might wanna display with a draggable widget. The first one is just the default child, which is what will be displayed when the user is not interacting with it. When the user starts to drag, that will open the door to 2 additional UI elements. The initial child disappears and then we have this feedback widget, which is what is actually being dragged around the screen. And then we also have the option to define a child when dragging widget which will be displayed to replace the original child when it's being dragged. Now getting back to our code, there's one important thing I want to point out here and that's that if you're passing data from a draggable widget to a drop target, you should provide it with a generic type that represents the data that you're passing to the drop target, which in our case is just a string. Then to actually pass the data, we'll go ahead and define the data property as our emoji. Now at this point, we're ready to define the 3 different widgets which include, again, the child, the feedback, and the child when dragging. Now depending on your UI, this may be a good opportunity to refactor your code into a different widget. In our case here, all 3 of these widgets are very similar, so we'll go ahead and define a new stateless widget called emoji that takes a string emoji as an input. Then down here in the build method, I'll start by defining a material widget. And the reason I'm starting with this material widget is because for whatever reason, the draggable feedback doesn't seem to want to inherit the text styles from the main app. And then the rest of it is just very basic Flutter stuff like a container that's aligned to the center that has a specific height and width. But because we extracted this logic into its own stateless widget, we can now reuse it 3 times up in the draggable widget in a very dry and maintainable way. So we can use our emoji widget up here as the child, and when passing in the actual emoji argument, we'll go ahead and check to see if that one's already been answered correctly. If it's been answered Correctly, we'll just display a check mark. Otherwise, we'll display the emoji itself. For the feedback widget, we'll always just want to display the emoji, but you might want to add some box shadow or maybe make it larger here to give it the effect of being grabbed. And, lastly, we can use the emoji widget as the child when dragging property as well. And that's all it takes to build a draggable widget, and there's also a number of different callbacks that you can listen to on draggable to handle different UI interactions based on the state of what's being dragged. But in many cases, you want to drag something to a specific location and have it interact with a different widget, which we can do with a drop target. In our case, we're going to build multiple drop targets, and each one of those targets corresponds to a specific emoji that is allowed to be dropped on top of it. We'll go ahead and loop over the keys in the choices map again, but this time I'm going to define a function called build drag target that will build the widgets for each individual drop zone. Then I'm going to call dot dot shuffle with our random seed, and that will randomize the order of the items in this list. The two dots here are called cascade Cade notation in Dart, and they allow you to make a sequence of operations on the same object. In this case, shuffle doesn't actually return the array. It just mutates the original. So So without the cascade notation, we'd have to create a temporary variable just to shuffle the array which would take a few more lines of code. That's just one of the many ways that Dart makes life a little bit easier for you. Now we're ready to define the actual drag target, and we wanna make sure to pass in the generic string type here for the data type that we're dropping on top of this target. The next thing we'll do is define its builder function, which gives us access to the build context, a list of accepted data, and a list of rejected data. We can use that data to determine how the UI should look for the drag target. Now, in our case, we're keeping track of the score on the parent stateful widget, which means we can just look at the score map for this particular emoji to determine which UI elements to show. If the users already answered this one Then we'll just display a white container that has the text of correct. But if the user has not answered this one correctly, then we'll go ahead and display a container that has the corresponding color to that emoji. And again, that data is contained in the choices map, which we defined at the beginning of the video. But how do we know whether or not a user has Will they drop something on the drag target, and whether or not that's valid data to be dropped there in the first place? We can decide if the data is valid or not by defining this on will accept function. This will fire when the user drags something on top of the target. So in our case, we can look at the data or the emoji string and make sure that it matches the emoji of this particular widget. In other words, you should only be able to drop the tomato on the red drop zone. That'll fire when the user first hovers over the drag target. But when they actually drop the item and it's accepted, it will fire this on accept function. And we also have on leave if it's dropped and it's not accepted or if they just leave the drop zone altogether. When the user makes a successful drop, we'll go ahead and call set state and update the score on the stateful widget. In addition, we can also play a sound here, which we can easily do with our audio controller by calling play and then passing it the name of our MP 3 file. And that's all there is to it. We now have a fully functional drag and drop UI, and I think the only possible way to make it better would be to add in some annoying mobile ads, But we'll save that for another episode. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe and consider becoming a pro member at Fireship IO to get access to the Upcoming Flutter course. Thanks for watching, and I will talk to you soon. I choose chunky style build because it has the wholesome chunks growing kids need.
Yesterday,
yesterday
my
my
2
2
year
year
old
old
was
was
playing
playing
with
with
a
a
book
book
that
that
has
has
you
you
connect
connect
a
a
color
color
to
to
a
a
fruit.
fruit
And
and
I
i
realized
realized
that
that
would
would
be
be
the
the
perfect
perfect
feature
feature
to
to
demonstrate
demonstrate
drag
drag
and
and
drop
drop
and
and
flutter.
flutter
In
in
today's
today's
video,
video
we'll
we'll
build
build
a
a
simple
simple
kids
kids
game
game
that
that
allows
allows
you
you
to
to
drag
drag
a
a
fruit
fruit
over
over
to
to
a
a
square
square
with
with
the
the
corresponding
corresponding
color.
color
If
if
you
you
drop
drop
it
it
on
on
the
the
correct
correct
square,
square
it
it
will
will
update
update
the
the
score
score
and
and
also
also
give
give
you
you
some
some
audio
audio
feedback.
feedback
If
if
you're
you're
new
new
here,
here
like
like
and
and
subscribe
subscribe
and
and
you
you
can
can
find
find
the
the
full
full
source
source
code
code
on
on
Fireship
fireship
IO.
io
Now,
now
before
before
we
we
get
get
started,
started
a
a
lot
lot
of
of
people
people
have
have
asked
asked
me
me
when
when
I'm
i'm
going
going
to
to
release
release
a
a
full
full
Flutter
flutter
course.
course
The
the
answer
answer
is
is
very
very
soon.
soon
It'll
it'll
be
be
released
released
before
before
Google
google
IO,
io
which
which
is
is
now
now
only
only
6
6
days
days
away,
away
So
so
expect
expect
more
more
details
details
on
on
that
that
in
in
the
the
next
next
few
few
days.
days
Now,
now
let's
let's
go
go
ahead
ahead
and
and
take
take
a
a
closer
closer
look
look
at
at
the
the
app
app
we're
we're
building
building
today.
today
You'll
you'll
see
see
2
2
columns
columns
here
here
and
and
you
you
can
can
grab
grab
an
an
item
item
from
from
the
the
column
column
on
on
the
the
left
left
and
and
then
then
drag
drag
it
it
to
to
a
a
target
target
on
on
the
the
right.
right
If
if
it's
it's
the
the
correct
correct
color,
color
it
it
will
will
mark
mark
it
it
as
as
correct
correct
and
and
then
then
update
update
the
the
score,
score
but
but
if
if
it's
it's
dropped
dropped
on
on
the
the
incorrect
incorrect
target,
target
then
then
it
it
will
will
just
just
go
go
back
back
to
to
its
its
original
original
position.
position
And
and
then
then
we'll
we'll
also
also
randomize
randomize
the
the
ordering
ordering
of
of
the
the
targets
targets
for
for
each
each
round
round
just
just
so
so
there's
there's
a
a
little
little
bit
bit
of
of
replay
replay
value.
value
And
and
as
as
an
an
added
added
touch,
touch
we'll
we'll
play
play
a
a
little
little
sound
sound
effect
effect
every
every
time
time
the
the
user
user
makes
makes
a
a
successful
successful
drop.
drop
If
if
we
we
jump
jump
into
into
the
the
code,
code
the
the
first
first
thing
thing
we'll
we'll
look
look
at
at
is
is
the
the
pubspec.
pubspec
Yaml
yaml
file.
file
The
the
only
only
dependency
dependency
outside
outside
of
of
Flutter
flutter
is
is
this
this
audio
audio
players
players
plug
plug
in.
in
I
i
really
really
like
like
this
this
plugin
plugin
because
because
it
it
works
works
on
on
both
both
iOS
ios
and
and
Android
android
and
and
also
also
allows
allows
you
you
to
to
play
play
multiple
multiple
audio
audio
files
files
simultaneously,
simultaneously
and
and
that
that
tends
tends
to
to
be
be
pretty
pretty
important
important
if
if
you're
you're
building
building
a
a
game.
game
And
and
you'll
you'll
also
also
notice
notice
that
that
we
we
have
have
an
an
MP
mp
3
3
file
file
here
here
registered
registered
in
in
the
the
assets
assets
directory,
directory
and
and
I've
i've
also
also
registered
registered
a
a
custom
custom
font
font
called
called
Press
press
Start,
start
which
which
you
you
can
can
download
download
from
from
Google
google
Fonts
fonts
that'll
that'll
give
give
you
you
that
that
kind
kind
pixelated
pixelated
retro
retro
look.
look
Now
now
moving
moving
on
on
to
to
the
the
source
source
code,
code
I'm
i'm
importing
importing
dart
dart
math
math
as
as
well
well
as
as
the
the
audio
audio
players
players
plug
plug
in.
in
Then
then
we'll
we'll
update
update
the
the
font
font
family
family
and
and
our
our
theme
theme
data,
data
and
and
then
then
we'll
we'll
set
set
the
the
homepage
homepage
as
as
this
this
color
color
game
game
screen
screen
that
that
we're
we're
about
about
to
to
define
define
now.
now
The
the
screen
screen
itself
itself
is
is
a
a
stateful
stateful
widget,
widget
and
and
the
the
first
first
property
property
we'll
we'll
define
define
is
is
the
the
score,
score
which
which
just
just
starts
starts
out
out
as
as
an
an
empty
empty
map.
map
Eventually,
eventually
we'll
we'll
update
update
the
the
keys
keys
on
on
this
this
map
map
when
when
the
the
user
user
drags
drags
a
a
draggable
draggable
widget
widget
onto
onto
the
the
correct
correct
drag
drag
target.
target
The
the
next
next
thing
thing
we'll
we'll
define
define
is
is
a
a
map
map
of
of
choices,
choices
and
and
so
so
each
each
emoji,
emoji
which
which
is
is
a
a
string,
string
will
will
map
map
to
to
a
a
material
material
color.
color
Emojis
emojis
are
are
really
really
handy
handy
because
because
they
they
not
not
only
only
provide
provide
a
a
graphic
graphic
that
that
we
we
can
can
use
use
for
for
the
the
UI,
ui
but
but
we
we
can
can
also
also
use
use
them
them
to
to
organize
organize
the
the
game
game
logic
logic
itself.
itself
For
for
example,
example
if
if
the
the
user
user
correctly
correctly
drags
drags
to
to
the
the
green
green
square,
square
then
then
we
we
can
can
update
update
the
the
score
score
with
with
the
the
corresponding
corresponding
emoji
emoji
key.
key
We'll
we'll
We'll
we'll
also
also
define
define
an
an
integer
integer
here
here
called
called
seed,
seed
which
which
will
will
be
be
used
used
as
as
a
a
random
random
seed
seed
to
to
shuffle
shuffle
the
the
order
order
of
of
the
the
items
items
as
as
we
we
loop
loop
over
over
them.
them
And
and
then
then
we'll
we'll
use
use
the
the
audio
audio
cache
cache
class
class
to
to
play
play
a
a
local
local
m
m
p
p
3
3
file,
file
and
and
we'll
we'll
call
call
that
that
our
our
audio
audio
controller.
controller
From
from
there,
there
we'll
we'll
set
set
up
up
a
a
scaffold,
scaffold
and
and
in
in
the
the
app
app
bar
bar
for
for
that
that
scaffold,
scaffold
we'll
we'll
display
display
the
the
score,
score
And
and
then
then
we'll
we'll
have
have
a
a
floating
floating
action
action
button
button
that
that
allows
allows
the
the
user
user
to
to
reset
reset
the
the
game.
game
We
we
can
can
display
display
the
the
score
score
by
by
setting
setting
up
up
a
a
text
text
widget,
widget
and
and
then
then
to
to
calculate
calculate
the
the
score,
score
all
all
we
we
have
have
to
to
do
do
is
is
look
look
at
at
the
the
length
length
of
of
that
that
score
score
map.
map
And
and
you
you
can
can
use
use
the
the
dollar
dollar
sign
sign
brackets
brackets
to
to
interpolate
interpolate
an
an
expression
expression
directly
directly
inside
inside
of
of
a
a
string
string
and
and
dart.
dart
Now
now
the
the
purpose
purpose
of
of
the
the
floating
floating
action
action
button
button
is
is
to
to
reset
reset
the
the
game.
game
So
so
in
in
order
order
to
to
do
do
that,
that
we'll
we'll
call
call
set
set
state,
state
and
and
then
then
we'll
we'll
clear
clear
out
out
all
all
of
of
the
the
key
key
value
value
pairs
pairs
inside
inside
of
of
that
that
score
score
map.
map
And
and
we
we
also
also
want
want
to
to
add
add
some
some
randomness
randomness
after
after
each
each
game,
game
so
so
we'll
we'll
increment
increment
our
our
random
random
seed
seed
by
by
1.
1
That
that
takes
takes
care
care
of
of
the
the
outer
outer
UI.
ui
Now
now
we'll
we'll
set
set
up
up
a
a
row
row
that
that
has
has
2
2
columns
columns
laid
laid
out
out
side
side
by
by
side,
side
the
the
draggable
draggable
stuff
stuff
on
on
the
the
left
left
with
with
the
the
drop
drop
targets
targets
on
on
the
the
right.
right
So
so
the
the
first
first
column
column
in
in
the
the
row
row
will
will
take
take
care
care
of
of
the
the
draggable
draggable
widgets,
widgets
and
and
we'll
we'll
want
want
each
each
of
of
our
our
6
6
choices
choices
to
to
be
be
a
a
draggable
draggable
widget.
widget
So
so
we'll
we'll
go
go
ahead
ahead
and
and
loop
loop
over
over
the
the
keys
keys
in
in
the
the
map.
map
And
and
if
if
you
you
remember
remember
from
from
earlier,
earlier
each
each
key
key
in
in
that
that
map
map
is
is
just
just
an
an
emoji
emoji
string.
string
Now
now
we're
we're
ready
ready
to
to
start
start
using
using
Flutter's
flutter's
draggable
draggable
widget,
widget
which
which
allows
allows
the
the
user
user
to
to
drag
drag
a
a
child
child
widget
widget
around
around
the
the
screen.
screen
Now
now
there
there
are
are
3
3
different
different
things
things
you
you
might
might
wanna
wanna
display
display
with
with
a
a
draggable
draggable
widget.
widget
The
the
first
first
one
one
is
is
just
just
the
the
default
default
child,
child
which
which
is
is
what
what
will
will
be
be
displayed
displayed
when
when
the
the
user
user
is
is
not
not
interacting
interacting
with
with
it.
it
When
when
the
the
user
user
starts
starts
to
to
drag,
drag
that
that
will
will
open
open
the
the
door
door
to
to
2
2
additional
additional
UI
ui
elements.
elements
The
the
initial
initial
child
child
disappears
disappears
and
and
then
then
we
we
have
have
this
this
feedback
feedback
widget,
widget
which
which
is
is
what
what
is
is
actually
actually
being
being
dragged
dragged
around
around
the
the
screen.
screen
And
and
then
then
we
we
also
also
have
have
the
the
option
option
to
to
define
define
a
a
child
child
when
when
dragging
dragging
widget
widget
which
which
will
will
be
be
displayed
displayed
to
to
replace
replace
the
the
original
original
child
child
when
when
it's
it's
being
being
dragged.
dragged
Now
now
getting
getting
back
back
to
to
our
our
code,
code
there's
there's
one
one
important
important
thing
thing
I
i
want
want
to
to
point
point
out
out
here
here
and
and
that's
that's
that
that
if
if
you're
you're
passing
passing
data
data
from
from
a
a
draggable
draggable
widget
widget
to
to
a
a
drop
drop
target,
target
you
you
should
should
provide
provide
it
it
with
with
a
a
generic
generic
type
type
that
that
represents
represents
the
the
data
data
that
that
you're
you're
passing
passing
to
to
the
the
drop
drop
target,
target
which
which
in
in
our
our
case
case
is
is
just
just
a
a
string.
string
Then
then
to
to
actually
actually
pass
pass
the
the
data,
data
we'll
we'll
go
go
ahead
ahead
and
and
define
define
the
the
data
data
property
property
as
as
our
our
emoji.
emoji
Now
now
at
at
this
this
point,
point
we're
we're
ready
ready
to
to
define
define
the
the
3
3
different
different
widgets
widgets
which
which
include,
include
again,
again
the
the
child,
child
the
the
feedback,
feedback
and
and
the
the
child
child
when
when
dragging.
dragging
Now
now
depending
depending
on
on
your
your
UI,
ui
this
this
may
may
be
be
a
a
good
good
opportunity
opportunity
to
to
refactor
refactor
your
your
code
code
into
into
a
a
different
different
widget.
widget
In
in
our
our
case
case
here,
here
all
all
3
3
of
of
these
these
widgets
widgets
are
are
very
very
similar,
similar
so
so
we'll
we'll
go
go
ahead
ahead
and
and
define
define
a
a
new
new
stateless
stateless
widget
widget
called
called
emoji
emoji
that
that
takes
takes
a
a
string
string
emoji
emoji
as
as
an
an
input.
input
Then
then
down
down
here
here
in
in
the
the
build
build
method,
method
I'll
i'll
start
start
by
by
defining
defining
a
a
material
material
widget.
widget
And
and
the
the
reason
reason
I'm
i'm
starting
starting
with
with
this
this
material
material
widget
widget
is
is
because
because
for
for
whatever
whatever
reason,
reason
the
the
draggable
draggable
feedback
feedback
doesn't
doesn't
seem
seem
to
to
want
want
to
to
inherit
inherit
the
the
text
text
styles
styles
from
from
the
the
main
main
app.
app
And
and
then
then
the
the
rest
rest
of
of
it
it
is
is
just
just
very
very
basic
basic
Flutter
flutter
stuff
stuff
like
like
a
a
container
container
that's
that's
aligned
aligned
to
to
the
the
center
center
that
that
has
has
a
a
specific
specific
height
height
and
and
width.
width
But
but
because
because
we
we
extracted
extracted
this
this
logic
logic
into
into
its
its
own
own
stateless
stateless
widget,
widget
we
we
can
can
now
now
reuse
reuse
it
it
3
3
times
times
up
up
in
in
the
the
draggable
draggable
widget
widget
in
in
a
a
very
very
dry
dry
and
and
maintainable
maintainable
way.
way
So
so
we
we
can
can
use
use
our
our
emoji
emoji
widget
widget
up
up
here
here
as
as
the
the
child,
child
and
and
when
when
passing
passing
in
in
the
the
actual
actual
emoji
emoji
argument,
argument
we'll
we'll
go
go
ahead
ahead
and
and
check
check
to
to
see
see
if
if
that
that
one's
one's
already
already
been
been
answered
answered
correctly.
correctly
If
if
it's
it's
been
been
answered
answered
Correctly,
correctly
we'll
we'll
just
just
display
display
a
a
check
check
mark.
mark
Otherwise,
otherwise
we'll
we'll
display
display
the
the
emoji
emoji
itself.
itself
For
for
the
the
feedback
feedback
widget,
widget
we'll
we'll
always
always
just
just
want
want
to
to
display
display
the
the
emoji,
emoji
but
but
you
you
might
might
want
want
to
to
add
add
some
some
box
box
shadow
shadow
or
or
maybe
maybe
make
make
it
it
larger
larger
here
here
to
to
give
give
it
it
the
the
effect
effect
of
of
being
being
grabbed.
grabbed
And,
and
lastly,
lastly
we
we
can
can
use
use
the
the
emoji
emoji
widget
widget
as
as
the
the
child
child
when
when
dragging
dragging
property
property
as
as
well.
well
And
and
that's
that's
all
all
it
it
takes
takes
to
to
build
build
a
a
draggable
draggable
widget,
widget
and
and
there's
there's
also
also
a
a
number
number
of
of
different
different
callbacks
callbacks
that
that
you
you
can
can
listen
listen
to
to
on
on
draggable
draggable
to
to
handle
handle
different
different
UI
ui
interactions
interactions
based
based
on
on
the
the
state
state
of
of
what's
what's
being
being
dragged.
dragged
But
but
in
in
many
many
cases,
cases
you
you
want
want
to
to
drag
drag
something
something
to
to
a
a
specific
specific
location
location
and
and
have
have
it
it
interact
interact
with
with
a
a
different
different
widget,
widget
which
which
we
we
can
can
do
do
with
with
a
a
drop
drop
target.
target
In
in
our
our
case,
case
we're
we're
going
going
to
to
build
build
multiple
multiple
drop
drop
targets,
targets
and
and
each
each
one
one
of
of
those
those
targets
targets
corresponds
corresponds
to
to
a
a
specific
specific
emoji
emoji
that
that
is
is
allowed
allowed
to
to
be
be
dropped
dropped
on
on
top
top
of
of
it.
it
We'll
we'll
go
go
ahead
ahead
and
and
loop
loop
over
over
the
the
keys
keys
in
in
the
the
choices
choices
map
map
again,
again
but
but
this
this
time
time
I'm
i'm
going
going
to
to
define
define
a
a
function
function
called
called
build
build
drag
drag
target
target
that
that
will
will
build
build
the
the
widgets
widgets
for
for
each
each
individual
individual
drop
drop
zone.
zone
Then
then
I'm
i'm
going
going
to
to
call
call
dot
dot
dot
dot
shuffle
shuffle
with
with
our
our
random
random
seed,
seed
and
and
that
that
will
will
randomize
randomize
the
the
order
order
of
of
the
the
items
items
in
in
this
this
list.
list
The
the
two
two
dots
dots
here
here
are
are
called
called
cascade
cascade
Cade
cade
notation
notation
in
in
Dart,
dart
and
and
they
they
allow
allow
you
you
to
to
make
make
a
a
sequence
sequence
of
of
operations
operations
on
on
the
the
same
same
object.
object
In
in
this
this
case,
case
shuffle
shuffle
doesn't
doesn't
actually
actually
return
return
the
the
array.
array
It
it
just
just
mutates
mutates
the
the
original.
original
So
so
So
so
without
without
the
the
cascade
cascade
notation,
notation
we'd
we'd
have
have
to
to
create
create
a
a
temporary
temporary
variable
variable
just
just
to
to
shuffle
shuffle
the
the
array
array
which
which
would
would
take
take
a
a
few
few
more
more
lines
lines
of
of
code.
code
That's
that's
just
just
one
one
of
of
the
the
many
many
ways
ways
that
that
Dart
dart
makes
makes
life
life
a
a
little
little
bit
bit
easier
easier
for
for
you.
you
Now
now
we're
we're
ready
ready
to
to
define
define
the
the
actual
actual
drag
drag
target,
target
and
and
we
we
wanna
wanna
make
make
sure
sure
to
to
pass
pass
in
in
the
the
generic
generic
string
string
type
type
here
here
for
for
the
the
data
data
type
type
that
that
we're
we're
dropping
dropping
on
on
top
top
of
of
this
this
target.
target
The
the
next
next
thing
thing
we'll
we'll
do
do
is
is
define
define
its
its
builder
builder
function,
function
which
which
gives
gives
us
us
access
access
to
to
the
the
build
build
context,
context
a
a
list
list
of
of
accepted
accepted
data,
data
and
and
a
a
list
list
of
of
rejected
rejected
data.
data
We
we
can
can
use
use
that
that
data
data
to
to
determine
determine
how
how
the
the
UI
ui
should
should
look
look
for
for
the
the
drag
drag
target.
target
Now,
now
in
in
our
our
case,
case
we're
we're
keeping
keeping
track
track
of
of
the
the
score
score
on
on
the
the
parent
parent
stateful
stateful
widget,
widget
which
which
means
means
we
we
can
can
just
just
look
look
at
at
the
the
score
score
map
map
for
for
this
this
particular
particular
emoji
emoji
to
to
determine
determine
which
which
UI
ui
elements
elements
to
to
show.
show
If
if
the
the
users
users
already
already
answered
answered
this
this
one
one
Then
then
we'll
we'll
just
just
display
display
a
a
white
white
container
container
that
that
has
has
the
the
text
text
of
of
correct.
correct
But
but
if
if
the
the
user
user
has
has
not
not
answered
answered
this
this
one
one
correctly,
correctly
then
then
we'll
we'll
go
go
ahead
ahead
and
and
display
display
a
a
container
container
that
that
has
has
the
the
corresponding
corresponding
color
color
to
to
that
that
emoji.
emoji
And
and
again,
again
that
that
data
data
is
is
contained
contained
in
in
the
the
choices
choices
map,
map
which
which
we
we
defined
defined
at
at
the
the
beginning
beginning
of
of
the
the
video.
video
But
but
how
how
do
do
we
we
know
know
whether
whether
or
or
not
not
a
a
user
user
has
has
Will
will
they
they
drop
drop
something
something
on
on
the
the
drag
drag
target,
target
and
and
whether
whether
or
or
not
not
that's
that's
valid
valid
data
data
to
to
be
be
dropped
dropped
there
there
in
in
the
the
first
first
place?
place
We
we
can
can
decide
decide
if
if
the
the
data
data
is
is
valid
valid
or
or
not
not
by
by
defining
defining
this
this
on
on
will
will
accept
accept
function.
function
This
this
will
will
fire
fire
when
when
the
the
user
user
drags
drags
something
something
on
on
top
top
of
of
the
the
target.
target
So
so
in
in
our
our
case,
case
we
we
can
can
look
look
at
at
the
the
data
data
or
or
the
the
emoji
emoji
string
string
and
and
make
make
sure
sure
that
that
it
it
matches
matches
the
the
emoji
emoji
of
of
this
this
particular
particular
widget.
widget
In
in
other
other
words,
words
you
you
should
should
only
only
be
be
able
able
to
to
drop
drop
the
the
tomato
tomato
on
on
the
the
red
red
drop
drop
zone.
zone
That'll
that'll
fire
fire
when
when
the
the
user
user
first
first
hovers
hovers
over
over
the
the
drag
drag
target.
target
But
but
when
when
they
they
actually
actually
drop
drop
the
the
item
item
and
and
it's
it's
accepted,
accepted
it
it
will
will
fire
fire
this
this
on
on
accept
accept
function.
function
And
and
we
we
also
also
have
have
on
on
leave
leave
if
if
it's
it's
dropped
dropped
and
and
it's
it's
not
not
accepted
accepted
or
or
if
if
they
they
just
just
leave
leave
the
the
drop
drop
zone
zone
altogether.
altogether
When
when
the
the
user
user
makes
makes
a
a
successful
successful
drop,
drop
we'll
we'll
go
go
ahead
ahead
and
and
call
call
set
set
state
state
and
and
update
update
the
the
score
score
on
on
the
the
stateful
stateful
widget.
widget
In
in
addition,
addition
we
we
can
can
also
also
play
play
a
a
sound
sound
here,
here
which
which
we
we
can
can
easily
easily
do
do
with
with
our
our
audio
audio
controller
controller
by
by
calling
calling
play
play
and
and
then
then
passing
passing
it
it
the
the
name
name
of
of
our
our
MP
mp
3
3
file.
file
And
and
that's
that's
all
all
there
there
is
is
to
to
it.
it
We
we
now
now
have
have
a
a
fully
fully
functional
functional
drag
drag
and
and
drop
drop
UI,
ui
and
and
I
i
think
think
the
the
only
only
possible
possible
way
way
to
to
make
make
it
it
better
better
would
would
be
be
to
to
add
add
in
in
some
some
annoying
annoying
mobile
mobile
ads,
ads
But
but
we'll
we'll
save
save
that
that
for
for
another
another
episode.
episode
I'm
i'm
gonna
gonna
go
go
ahead
ahead
and
and
wrap
wrap
things
things
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe
subscribe
and
and
consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
Fireship
fireship
IO
io
to
to
get
get
access
access
to
to
the
the
Upcoming
upcoming
Flutter
flutter
course.
course
Thanks
thanks
for
for
watching,
watching
and
and
I
i
will
will
talk
talk
to
to
you
you
soon.
soon
I
i
choose
choose
chunky
chunky
style
style
build
build
because
because
it
it
has
has
the
the
wholesome
wholesome
chunks
chunks
growing
growing
kids
kids
need.
need
success
The speakers discuss various features of the Flutter app, including a fruit drilled with a color and a backend feature for the Flutter app. They also discuss the use of file cache and audio player plug in, the placement of the target, and the use of a variable to reset the game. They explain how to define a function called "build drag target" and how to use it in the command line, as well as how to define the build drag target and set the state of the element. They also mention the use of a fully functional drag and drop UI and suggest adding mobile ads.
Flutter Drag & Drop for Two-Year-Olds
Yesterday, my 2 year old was playing with a book that has you connect a color to a fruit. And I realized that would be the perfect feature to demonstrate drag and drop and flutter. In today's video, we'll build a simple kids game that allows you to drag a fruit over to a square with the corresponding color. If you drop it on the correct square, it will update the score and also give you some audio feedback. If you're new here, like and subscribe and you can find the full source code on Fireship IO. Now, before we get started, a lot of people have asked me when I'm going to release a full Flutter course. The answer is very soon. It'll be released before Google IO, which is now only 6 days away, So expect more details on that in the next few days. Now, let's go ahead and take a closer look at the app we're building today. You'll see 2 columns here and you can grab an item from the column on the left and then drag it to a target on the right. If it's the correct color, it will mark it as correct and then update the score, but if it's dropped on the incorrect target, then it will just go back to its original position. And then we'll also randomize the ordering of the targets for each round just so there's a little bit of replay value. And as an added touch, we'll play a little sound effect every time the user makes a successful drop. If we jump into the code, the first thing we'll look at is the pubspec. Yaml file. The only dependency outside of Flutter is this audio players plug in. I really like this plugin because it works on both iOS and Android and also allows you to play multiple audio files simultaneously, and that tends to be pretty important if you're building a game. And you'll also notice that we have an MP 3 file here registered in the assets directory, and I've also registered a custom font called Press Start, which you can download from Google Fonts that'll give you that kind pixelated retro look. Now moving on to the source code, I'm importing dart math as well as the audio players plug in. Then we'll update the font family and our theme data, and then we'll set the homepage as this color game screen that we're about to define now. The screen itself is a stateful widget, and the first property we'll define is the score, which just starts out as an empty map. Eventually, we'll update the keys on this map when the user drags a draggable widget onto the correct drag target. The next thing we'll define is a map of choices, and so each emoji, which is a string, will map to a material color. Emojis are really handy because they not only provide a graphic that we can use for the UI, but we can also use them to organize the game logic itself. For example, if the user correctly drags to the green square, then we can update the score with the corresponding emoji key. We'll We'll also define an integer here called seed, which will be used as a random seed to shuffle the order of the items as we loop over them. And then we'll use the audio cache class to play a local m p 3 file, and we'll call that our audio controller. From there, we'll set up a scaffold, and in the app bar for that scaffold, we'll display the score, And then we'll have a floating action button that allows the user to reset the game. We can display the score by setting up a text widget, and then to calculate the score, all we have to do is look at the length of that score map. And you can use the dollar sign brackets to interpolate an expression directly inside of a string and dart. Now the purpose of the floating action button is to reset the game. So in order to do that, we'll call set state, and then we'll clear out all of the key value pairs inside of that score map. And we also want to add some randomness after each game, so we'll increment our random seed by 1. That takes care of the outer UI. Now we'll set up a row that has 2 columns laid out side by side, the draggable stuff on the left with the drop targets on the right. So the first column in the row will take care of the draggable widgets, and we'll want each of our 6 choices to be a draggable widget. So we'll go ahead and loop over the keys in the map. And if you remember from earlier, each key in that map is just an emoji string. Now we're ready to start using Flutter's draggable widget, which allows the user to drag a child widget around the screen. Now there are 3 different things you might wanna display with a draggable widget. The first one is just the default child, which is what will be displayed when the user is not interacting with it. When the user starts to drag, that will open the door to 2 additional UI elements. The initial child disappears and then we have this feedback widget, which is what is actually being dragged around the screen. And then we also have the option to define a child when dragging widget which will be displayed to replace the original child when it's being dragged. Now getting back to our code, there's one important thing I want to point out here and that's that if you're passing data from a draggable widget to a drop target, you should provide it with a generic type that represents the data that you're passing to the drop target, which in our case is just a string. Then to actually pass the data, we'll go ahead and define the data property as our emoji. Now at this point, we're ready to define the 3 different widgets which include, again, the child, the feedback, and the child when dragging. Now depending on your UI, this may be a good opportunity to refactor your code into a different widget. In our case here, all 3 of these widgets are very similar, so we'll go ahead and define a new stateless widget called emoji that takes a string emoji as an input. Then down here in the build method, I'll start by defining a material widget. And the reason I'm starting with this material widget is because for whatever reason, the draggable feedback doesn't seem to want to inherit the text styles from the main app. And then the rest of it is just very basic Flutter stuff like a container that's aligned to the center that has a specific height and width. But because we extracted this logic into its own stateless widget, we can now reuse it 3 times up in the draggable widget in a very dry and maintainable way. So we can use our emoji widget up here as the child, and when passing in the actual emoji argument, we'll go ahead and check to see if that one's already been answered correctly. If it's been answered Correctly, we'll just display a check mark. Otherwise, we'll display the emoji itself. For the feedback widget, we'll always just want to display the emoji, but you might want to add some box shadow or maybe make it larger here to give it the effect of being grabbed. And, lastly, we can use the emoji widget as the child when dragging property as well. And that's all it takes to build a draggable widget, and there's also a number of different callbacks that you can listen to on draggable to handle different UI interactions based on the state of what's being dragged. But in many cases, you want to drag something to a specific location and have it interact with a different widget, which we can do with a drop target. In our case, we're going to build multiple drop targets, and each one of those targets corresponds to a specific emoji that is allowed to be dropped on top of it. We'll go ahead and loop over the keys in the choices map again, but this time I'm going to define a function called build drag target that will build the widgets for each individual drop zone. Then I'm going to call dot dot shuffle with our random seed, and that will randomize the order of the items in this list. The two dots here are called cascade Cade notation in Dart, and they allow you to make a sequence of operations on the same object. In this case, shuffle doesn't actually return the array. It just mutates the original. So So without the cascade notation, we'd have to create a temporary variable just to shuffle the array which would take a few more lines of code. That's just one of the many ways that Dart makes life a little bit easier for you. Now we're ready to define the actual drag target, and we wanna make sure to pass in the generic string type here for the data type that we're dropping on top of this target. The next thing we'll do is define its builder function, which gives us access to the build context, a list of accepted data, and a list of rejected data. We can use that data to determine how the UI should look for the drag target. Now, in our case, we're keeping track of the score on the parent stateful widget, which means we can just look at the score map for this particular emoji to determine which UI elements to show. If the users already answered this one Then we'll just display a white container that has the text of correct. But if the user has not answered this one correctly, then we'll go ahead and display a container that has the corresponding color to that emoji. And again, that data is contained in the choices map, which we defined at the beginning of the video. But how do we know whether or not a user has Will they drop something on the drag target, and whether or not that's valid data to be dropped there in the first place? We can decide if the data is valid or not by defining this on will accept function. This will fire when the user drags something on top of the target. So in our case, we can look at the data or the emoji string and make sure that it matches the emoji of this particular widget. In other words, you should only be able to drop the tomato on the red drop zone. That'll fire when the user first hovers over the drag target. But when they actually drop the item and it's accepted, it will fire this on accept function. And we also have on leave if it's dropped and it's not accepted or if they just leave the drop zone altogether. When the user makes a successful drop, we'll go ahead and call set state and update the score on the stateful widget. In addition, we can also play a sound here, which we can easily do with our audio controller by calling play and then passing it the name of our MP 3 file. And that's all there is to it. We now have a fully functional drag and drop UI, and I think the only possible way to make it better would be to add in some annoying mobile ads, But we'll save that for another episode. I'm gonna go ahead and wrap things up there. If this video helped you, please like and subscribe and consider becoming a pro member at Fireship IO to get access to the Upcoming Flutter course. Thanks for watching, and I will talk to you soon. I choose chunky style build because it has the wholesome chunks growing kids need.
The speakers discuss various features of the Flutter app, including a fruit drilled with a color and a backend feature for the Flutter app. They also discuss the use of file cache and audio player plug in, the placement of the target, and the use of a variable to reset the game. They explain how to define a function called "build drag target" and how to use it in the command line, as well as how to define the build drag target and set the state of the element. They also mention the use of a fully functional drag and drop UI and suggest adding mobile ads.