Build an animated slideshow in Flutter using the PageView widget, then make it filterable with Cloud Firestore https://fireship.io/lessons/flutter-slider-like-reflectly/

Reflectly https://reflectly.app/
PageView Widget https://docs.flutter.io/flutter/widgets/PageView-class.html
Firestore https://firebase.google.com/docs/firestore/
2024-02-04T06:53:31.443Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
46438b98-f485-4653-b147-0befc13edb23
beffa954d89ff164322489c240f5f7372ef0f6a0584da684f5a3a7956ea973ed
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
One of the most popular showcase apps for Flutter is Reflectly.
It's an AI powered journal, and the developers did a really awesome job designing the UI.
In today's video, we'll build our own animated slideshow from scratch using this app as our inspiration.
Not only will it have this fluid transition between pages, but it will also be wired up with Firestore so we can filter the data on the back end.
And we'll do the entire thing in about a 100 lines of code.
If you're new to the channel, like and subscribe and you can find the full source code on FireShip.
Io.
Let's take a closer look at the demo.
When the user swipes, they can see a preview of the next page on the right and a preview of the previous page on the left.
The active page in the middle will animate into the view by increasing its height and also add a box shadow to give it depth.
The buttons on the first card will actually make a query to Firestore so we can filter the number of pages that are shown in the list.
Everything stays synced up in real time, so if we want to add another page, all we do is add some data to Firestore, and it's automatically reflected in the UI.
We're going to look at a handful of important widgets here, but the single most important one is the page view.
Too.
It's a built in widget that comes with gesture detection and animation, allowing the user to swipe between a linear set of pages or widgets.
I want to show you how the page view works before we get into the main feature.
When When we jump into a basic Flutter app, the first thing we'll do is set up a page controller.
That controller allows you to navigate between pages manually and also gives you information about the state of the page view.
For a basic slider, you actually don't really need to do anything with the controller.
You just need to pass it in as an argument to the page view widget in the widget tree.
The next thing we'll do is add the page view widget as the body of our scaffold.
And a cool little side note is that you can control the scroll direction as either vertical or horizontal.
From there, we'll pass star controller, and then we'll define an array of children widgets.
I'm just going to hard code a few containers in here to show you the effect.
Because we have the scroll direction set to vertical, we can swipe from top to bottom to navigate between the pages.
So now that you know how a page view works, you can go ahead and delete all that code, and we're going to build something a lot more advanced.
At this point, I'm assuming that you have Firebase installed in your Flutter project.
If not, you'll want to stop right here and follow the official Flutter fire setup guide.
Back in the code, you'll see that I'm importing Firestore, and then I have our Firestore slideshow set up as the body of the scaffold.
And then I have an empty Stateful widget.
The Stateful widget will encapsulate this entire feature.
Let's start by taking a look at the different properties that we'll need on this widget.
The first one is our page controller, and we have an important option here called viewport fraction, which I've set to 0.8.
By default, each page will take up 100% of the viewport, but setting that fraction to 0.8 will allow the previous and next page to overflow a little bit into the screen.
The next thing we'll do is set up the instance of Firestore so we can interact with the back end database.
Then we'll define a stream of slides.
This will be the actual data from the database that we read to display the pages in the page view, and then we'll allow the user to filter them based on a certain tag.
And we'll just set the default tag to favorites.
And the last thing we'll do is keep track of the current page index so we can avoid unnecessary renders and just optimize performance.
Now there are two reasons for us to rerender this widget.
The first one is if the underlying data changes.
So on a knit state, we'll query the database, but then the user will also have the option to click a button to make a new query, which will then cause us to rerender the widget.
And then we'll also set up a listener on the actual page controller itself, and this fires an event anytime the state of the page controller changes.
It'll give you the exact fraction of the page that's available in the view, but we'll go ahead and round that to an integer because we really only care about a will page change that we can animate into the view by adding a box shadow and increasing the height.
We'll go ahead and call set state when the active page changes, and then I'll show you how to build the animation in a few minutes here.
The next thing we'll wanna focus on is getting our actual data from Firestore.
When the component is first initialized, we'll query the database using the default tag of favorites.
Now before we implement the code, let's take a look at the database.
We have a collection of stories and then we have a few documents in that collection.
Each document contains the data for a page.
So it has a background image and a title, which are both strings.
And then we have a property called tags, which is an array of strings.
We're going to query Firestore based on the data in this array.
For For example, if the user clicks on the happy tag, it will only query the documents that have the happy tag in the array in the database.
That gives us a very easy way to model tags on the back end, but just keep in mind that you can only query by 1 tag at a time.
So that's an important limitation to think about if you need to filter by multiple tags at the same time.
We'll define a method called query DB that takes a tag as its argument.
We'll set up the query by first making a reference to the stories collection, that we call where tags array contains the tag that's passed in as the argument.
That's all it takes to query the database.
And now that we have that query, we want to map it to the tool, data payload that's in the database.
For that, we have to take the stream of document snapshots and then map it down to the document data for each document in that array.
First, we call map on the stream and then we call map on the list that's contained inside that stream.
And then we call doc data, so we have the actual raw data from the database.
And the last thing I wanna do is call set state on the stateful widget so we can update the active tag when this method is called.
Now we have everything in place to start implementing the widgets build method.
In.
We'll start by returning a stream builder that takes these slides as its stream argument, and then we'll set some initial data as an empty array.
The stream builder allows the widget to react in real time if any of the back end data changes.
We'll call this builder method with a snapshot of the stream whenever a change occurs.
Inside the builder, I'm going to define a variable called slide list, which is the exact data that we have contained in the Firestore database.
After that, I'm going to set up our page view widget, but instead of passing it a static array of children, I'm going to use its builder method.
The builder method will only render the pages that are actually visible on the fly.
So that means it can scale up to an infinite number of pages depending on how much data you have in Firestore.
We'll first need to pass in our page controller, and then we'll set the item count to the slide list length.
And we'll add one to it, and that extra one represents the initial page of links that will show as the first page in the page view.
Now this takes a builder method that provides the context and the current index of the visible page.
We have 2 different types of pages we wanna display here.
The first one is that initial tag page, which allows the user to click on buttons to filter the number of slides in the page view.
We'll show that if the visible index equals 0.
Otherwise, we want to build one of the animated story pages.
And for that, we need to determine if that particular page is active.
We're already keeping track of the current page on this widget, so So all we have to do is compare the current index to the current page.
And then we'll extract the logic out to another build function called build story page, and it will take the raw data as the first argument and in the Boolean active value as its second argument.
That takes care of the logic for the slideshow as a whole, but now we need to build out the individual pages.
We'll build the story page first, which is just a container with an image background, some rounded corners, and a box shadow.
The method takes 2 arguments.
Again, the first one is the data from Firestore for this particular document.
And the second one is a Boolean, which tells us whether or not this widget is actively swipe to in the page view.
The next thing we'll do is define a few variables here, which will be different depending on whether or not the widget is active.
These are the properties that we want to animate.
For example, when the widget is active, we want to give it a blur and an offset.
But if the widget is not active, then we just want to set those values to 0.
And then we'll decrease the margin on the top when the widget is active so it appears taller when it's in the middle.
The really cool thing about this is we can make all these animations happen automatically by using an animated container.
Are.
Flutter will automatically perform an animation when any of the properties on this widget change.
We just need to provide it with a duration, which we'll set at 500 milliseconds and also a timing curve.
You can select any curve you want here.
They all look pretty good.
The next thing we'll do is set the margin.
And notice that the top margin is using our animated property while the bottom and right are just hard coded as integer values.
From there, we'll define the box decoration for this container.
We can give it rounded edges by defining a border radius, then setting a circular radius of around 20.
The next thing we'll do is define a background image as a decoration image, and we'll have it fit the entire height and width of the viewport by calling box fit cover.
The image itself will be loaded over the Internet based on that image's URL.
In Flutter, we can do that with the network image widget, then we'll pass in the image URL that we get from the Firestore database.
And the last piece of decoration that we wanna add here is a box shadow.
Will want to animate the radius and the offset so the card appears to levitate off the screen when it becomes active in the middle.
And because we're using an animated container, we don't need an animation controller, anything like that, Flutter handles all that stuff under the hood for us automatically.
When it comes to animation, it really doesn't get any easier than that.
And I almost forgot, you'll also want to add a child widget down here as well that includes the text to show the text from Firestore in the middle.
At this point, you should have the stories pages displaying correctly.
Our last step is to set up the buttons that allow the user to filter between the different pages.
Will be reusing the same button logic over and over again, so I'll define a method called build button that takes a tag as its argument.
If that tag is already applied, then I'm going to go ahead and color that button purple.
Otherwise, it'll be colored white.
The button text itself will just be the tag plus a hashtag.
Then when pressed, it will call the query DB method that we defined earlier.
And again that will call a set state on the widget as well as change the stream that we're listening to from Firestore.
Now that we have that logic in place we'll go ahead and actually build out the tag page.
It starts with a container.
And then inside that container, we have a column.
Then we'll go ahead and align the children in that column in the center vertically and then to the left on the horizontal axis.
Then we'll add a couple of text widgets, and then we'll build out the buttons that we need for the various tags.
I'm just going to hard code the tag names in there for now.
But in a real world app, you would most likely query those from the database because the user is going to be generating those tags dynamically.
I'm gonna go ahead and wrap things up there.
If this video helped you, please can subscribe.
And if you want even more content, consider becoming a pro member at Fireship I o.
That'll give you access to my full Flutter course which will be available in the next couple weeks.
Thanks for watching, and I will talk to you soon.

Speaker 0: One of the most popular showcase apps for Flutter is Reflectly. It's an AI powered journal, and the developers did a really awesome job designing the UI. In today's video, we'll build our own animated slideshow from scratch using this app as our inspiration. Not only will it have this fluid transition between pages, but it will also be wired up with Firestore so we can filter the data on the back end. And we'll do the entire thing in about a 100 lines of code.

If you're new to the channel, like and subscribe and you can find the full source code on FireShip. Io. Let's take a closer look at the demo. When the user swipes, they can see a preview of the next page on the right and a preview of the previous page on the left. The active page in the middle will animate into the view by increasing its height and also add a box shadow to give it depth.

The buttons on the first card will actually make a query to Firestore so we can filter the number of pages that are shown in the list. Everything stays synced up in real time, so if we want to add another page, all we do is add some data to Firestore, and it's automatically reflected in the UI. We're going to look at a handful of important widgets here, but the single most important one is the page view. Too. It's a built in widget that comes with gesture detection and animation, allowing the user to swipe between a linear set of pages or widgets.

I want to show you how the page view works before we get into the main feature. When When we jump into a basic Flutter app, the first thing we'll do is set up a page controller. That controller allows you to navigate between pages manually and also gives you information about the state of the page view. For a basic slider, you actually don't really need to do anything with the controller. You just need to pass it in as an argument to the page view widget in the widget tree.

The next thing we'll do is add the page view widget as the body of our scaffold. And a cool little side note is that you can control the scroll direction as either vertical or horizontal. From there, we'll pass star controller, and then we'll define an array of children widgets. I'm just going to hard code a few containers in here to show you the effect. Because we have the scroll direction set to vertical, we can swipe from top to bottom to navigate between the pages.

So now that you know how a page view works, you can go ahead and delete all that code, and we're going to build something a lot more advanced. At this point, I'm assuming that you have Firebase installed in your Flutter project. If not, you'll want to stop right here and follow the official Flutter fire setup guide. Back in the code, you'll see that I'm importing Firestore, and then I have our Firestore slideshow set up as the body of the scaffold. And then I have an empty Stateful widget.

The Stateful widget will encapsulate this entire feature. Let's start by taking a look at the different properties that we'll need on this widget. The first one is our page controller, and we have an important option here called viewport fraction, which I've set to 0.8. By default, each page will take up 100% of the viewport, but setting that fraction to 0.8 will allow the previous and next page to overflow a little bit into the screen. The next thing we'll do is set up the instance of Firestore so we can interact with the back end database.

Then we'll define a stream of slides. This will be the actual data from the database that we read to display the pages in the page view, and then we'll allow the user to filter them based on a certain tag. And we'll just set the default tag to favorites. And the last thing we'll do is keep track of the current page index so we can avoid unnecessary renders and just optimize performance. Now there are two reasons for us to rerender this widget.

The first one is if the underlying data changes. So on a knit state, we'll query the database, but then the user will also have the option to click a button to make a new query, which will then cause us to rerender the widget. And then we'll also set up a listener on the actual page controller itself, and this fires an event anytime the state of the page controller changes. It'll give you the exact fraction of the page that's available in the view, but we'll go ahead and round that to an integer because we really only care about a will page change that we can animate into the view by adding a box shadow and increasing the height. We'll go ahead and call set state when the active page changes, and then I'll show you how to build the animation in a few minutes here.

The next thing we'll wanna focus on is getting our actual data from Firestore. When the component is first initialized, we'll query the database using the default tag of favorites. Now before we implement the code, let's take a look at the database. We have a collection of stories and then we have a few documents in that collection. Each document contains the data for a page.

So it has a background image and a title, which are both strings. And then we have a property called tags, which is an array of strings. We're going to query Firestore based on the data in this array. For For example, if the user clicks on the happy tag, it will only query the documents that have the happy tag in the array in the database. That gives us a very easy way to model tags on the back end, but just keep in mind that you can only query by 1 tag at a time.

So that's an important limitation to think about if you need to filter by multiple tags at the same time. We'll define a method called query DB that takes a tag as its argument. We'll set up the query by first making a reference to the stories collection, that we call where tags array contains the tag that's passed in as the argument. That's all it takes to query the database. And now that we have that query, we want to map it to the tool, data payload that's in the database.

For that, we have to take the stream of document snapshots and then map it down to the document data for each document in that array. First, we call map on the stream and then we call map on the list that's contained inside that stream. And then we call doc data, so we have the actual raw data from the database. And the last thing I wanna do is call set state on the stateful widget so we can update the active tag when this method is called. Now we have everything in place to start implementing the widgets build method.

In. We'll start by returning a stream builder that takes these slides as its stream argument, and then we'll set some initial data as an empty array. The stream builder allows the widget to react in real time if any of the back end data changes. We'll call this builder method with a snapshot of the stream whenever a change occurs. Inside the builder, I'm going to define a variable called slide list, which is the exact data that we have contained in the Firestore database.

After that, I'm going to set up our page view widget, but instead of passing it a static array of children, I'm going to use its builder method. The builder method will only render the pages that are actually visible on the fly. So that means it can scale up to an infinite number of pages depending on how much data you have in Firestore. We'll first need to pass in our page controller, and then we'll set the item count to the slide list length. And we'll add one to it, and that extra one represents the initial page of links that will show as the first page in the page view.

Now this takes a builder method that provides the context and the current index of the visible page. We have 2 different types of pages we wanna display here. The first one is that initial tag page, which allows the user to click on buttons to filter the number of slides in the page view. We'll show that if the visible index equals 0. Otherwise, we want to build one of the animated story pages.

And for that, we need to determine if that particular page is active. We're already keeping track of the current page on this widget, so So all we have to do is compare the current index to the current page. And then we'll extract the logic out to another build function called build story page, and it will take the raw data as the first argument and in the Boolean active value as its second argument. That takes care of the logic for the slideshow as a whole, but now we need to build out the individual pages. We'll build the story page first, which is just a container with an image background, some rounded corners, and a box shadow.

The method takes 2 arguments. Again, the first one is the data from Firestore for this particular document. And the second one is a Boolean, which tells us whether or not this widget is actively swipe to in the page view. The next thing we'll do is define a few variables here, which will be different depending on whether or not the widget is active. These are the properties that we want to animate.

For example, when the widget is active, we want to give it a blur and an offset. But if the widget is not active, then we just want to set those values to 0. And then we'll decrease the margin on the top when the widget is active so it appears taller when it's in the middle. The really cool thing about this is we can make all these animations happen automatically by using an animated container. Are.

Flutter will automatically perform an animation when any of the properties on this widget change. We just need to provide it with a duration, which we'll set at 500 milliseconds and also a timing curve. You can select any curve you want here. They all look pretty good. The next thing we'll do is set the margin.

And notice that the top margin is using our animated property while the bottom and right are just hard coded as integer values. From there, we'll define the box decoration for this container. We can give it rounded edges by defining a border radius, then setting a circular radius of around 20. The next thing we'll do is define a background image as a decoration image, and we'll have it fit the entire height and width of the viewport by calling box fit cover. The image itself will be loaded over the Internet based on that image's URL.

In Flutter, we can do that with the network image widget, then we'll pass in the image URL that we get from the Firestore database. And the last piece of decoration that we wanna add here is a box shadow. Will want to animate the radius and the offset so the card appears to levitate off the screen when it becomes active in the middle. And because we're using an animated container, we don't need an animation controller, anything like that, Flutter handles all that stuff under the hood for us automatically. When it comes to animation, it really doesn't get any easier than that.

And I almost forgot, you'll also want to add a child widget down here as well that includes the text to show the text from Firestore in the middle. At this point, you should have the stories pages displaying correctly. Our last step is to set up the buttons that allow the user to filter between the different pages. Will be reusing the same button logic over and over again, so I'll define a method called build button that takes a tag as its argument. If that tag is already applied, then I'm going to go ahead and color that button purple.

Otherwise, it'll be colored white. The button text itself will just be the tag plus a hashtag. Then when pressed, it will call the query DB method that we defined earlier. And again that will call a set state on the widget as well as change the stream that we're listening to from Firestore. Now that we have that logic in place we'll go ahead and actually build out the tag page.

It starts with a container. And then inside that container, we have a column. Then we'll go ahead and align the children in that column in the center vertically and then to the left on the horizontal axis. Then we'll add a couple of text widgets, and then we'll build out the buttons that we need for the various tags. I'm just going to hard code the tag names in there for now.

But in a real world app, you would most likely query those from the database because the user is going to be generating those tags dynamically. I'm gonna go ahead and wrap things up there. If this video helped you, please can subscribe. And if you want even more content, consider becoming a pro member at Fireship I o. That'll give you access to my full Flutter course which will be available in the next couple weeks.

Thanks for watching, and I will talk to you soon.
One of the most popular showcase apps for Flutter is Reflectly. It's an AI powered journal, and the developers did a really awesome job designing the UI. In today's video, we'll build our own animated slideshow from scratch using this app as our inspiration. Not only will it have this fluid transition between pages, but it will also be wired up with Firestore so we can filter the data on the back end. And we'll do the entire thing in about a 100 lines of code. If you're new to the channel, like and subscribe and you can find the full source code on FireShip. Io. Let's take a closer look at the demo. When the user swipes, they can see a preview of the next page on the right and a preview of the previous page on the left. The active page in the middle will animate into the view by increasing its height and also add a box shadow to give it depth.
animation
multimedia
streaming
youtube
graphic design
The buttons on the first card will actually make a query to Firestore so we can filter the number of pages that are shown in the list. Everything stays synced up in real time, so if we want to add another page, all we do is add some data to Firestore, and it's automatically reflected in the UI.
commerce
We're going to look at a handful of important widgets here, but the single most important one is the page view. Too. It's a built in widget that comes with gesture detection and animation, allowing the user to swipe between a linear set of pages or widgets. I want to show you how the page view works before we get into the main feature.
visualization
When When we jump into a basic Flutter app, the first thing we'll do is set up a page controller. That controller allows you to navigate between pages manually and also gives you information about the state of the page view. For a basic slider, you actually don't really need to do anything with the controller. You just need to pass it in as an argument to the page view widget in the widget tree. The next thing we'll do is add the page view widget as the body of our scaffold. And a cool little side note is that you can control the scroll direction as either vertical or horizontal. From there, we'll pass star controller, and then we'll define an array of children widgets. I'm just going to hard code a few containers in here to show you the effect. Because we have the scroll direction set to vertical, we can swipe from top to bottom to navigate between the pages. So now that you know how a page view works, you can go ahead and delete all that code, and we're going to build something a lot more advanced. At this point, I'm assuming that you have Firebase installed in your Flutter project. If not, you'll want to stop right here and follow the official Flutter fire setup guide. Back in the code, you'll see that I'm importing Firestore, and then I have our Firestore slideshow set up as the body of the scaffold. And then I have an empty Stateful widget. The Stateful widget will encapsulate this entire feature. Let's start by taking a look at the different properties that we'll need on this widget. The first one is our page controller, and we have an important option here called viewport fraction, which I've set to 0.8. By default, each page will take up 100% of the viewport, but setting that fraction to 0.8 will allow the previous and next page to overflow a little bit into the screen.
The next thing we'll do is set up the instance of Firestore so we can interact with the back end database. Then we'll define a stream of slides. This will be the actual data from the database that we read to display the pages in the page view, and then we'll allow the user to filter them based on a certain tag. And we'll just set the default tag to favorites. And the last thing we'll do is keep track of the current page index so we can avoid unnecessary renders and just optimize performance.
databases
data management
websites
Now there are two reasons for us to rerender this widget. The first one is if the underlying data changes. So on a knit state, we'll query the database, but then the user will also have the option to click a button to make a new query, which will then cause us to rerender the widget. And then we'll also set up a listener on the actual page controller itself, and this fires an event anytime the state of the page controller changes. It'll give you the exact fraction of the page that's available in the view, but we'll go ahead and round that to an integer because we really only care about a will page change that we can animate into the view by adding a box shadow and increasing the height. We'll go ahead and call set state when the active page changes, and then I'll show you how to build the animation in a few minutes here.
The next thing we'll wanna focus on is getting our actual data from Firestore. When the component is first initialized, we'll query the database using the default tag of favorites. Now before we implement the code, let's take a look at the database. We have a collection of stories and then we have a few documents in that collection. Each document contains the data for a page. So it has a background image and a title, which are both strings. And then we have a property called tags, which is an array of strings. We're going to query Firestore based on the data in this array. For For example, if the user clicks on the happy tag, it will only query the documents that have the happy tag in the array in the database. That gives us a very easy way to model tags on the back end, but just keep in mind that you can only query by 1 tag at a time.
databases
data management
documentation
programming
data
So that's an important limitation to think about if you need to filter by multiple tags at the same time. We'll define a method called query DB that takes a tag as its argument.
We'll set up the query by first making a reference to the stories collection, that we call where tags array contains the tag that's passed in as the argument. That's all it takes to query the database. And now that we have that query, we want to map it to the tool, data payload that's in the database. For that, we have to take the stream of document snapshots and then map it down to the document data for each document in that array. First, we call map on the stream and then we call map on the list that's contained inside that stream. And then we call doc data, so we have the actual raw data from the database. And the last thing I wanna do is call set state on the stateful widget so we can update the active tag when this method is called.
databases
data
data management
Now we have everything in place to start implementing the widgets build method. In. We'll start by returning a stream builder that takes these slides as its stream argument, and then we'll set some initial data as an empty array.
The stream builder allows the widget to react in real time if any of the back end data changes. We'll call this builder method with a snapshot of the stream whenever a change occurs. Inside the builder, I'm going to define a variable called slide list, which is the exact data that we have contained in the Firestore database.
visualization
After that, I'm going to set up our page view widget, but instead of passing it a static array of children, I'm going to use its builder method. The builder method will only render the pages that are actually visible on the fly. So that means it can scale up to an infinite number of pages depending on how much data you have in Firestore. We'll first need to pass in our page controller, and then we'll set the item count to the slide list length. And we'll add one to it, and that extra one represents the initial page of links that will show as the first page in the page view.
Now this takes a builder method that provides the context and the current index of the visible page. We have 2 different types of pages we wanna display here. The first one is that initial tag page, which allows the user to click on buttons to filter the number of slides in the page view.
visualization
We'll show that if the visible index equals 0. Otherwise, we want to build one of the animated story pages. And for that, we need to determine if that particular page is active. We're already keeping track of the current page on this widget, so So all we have to do is compare the current index to the current page.
And then we'll extract the logic out to another build function called build story page, and it will take the raw data as the first argument and in the Boolean active value as its second argument. That takes care of the logic for the slideshow as a whole, but now we need to build out the individual pages. We'll build the story page first, which is just a container with an image background, some rounded corners, and a box shadow. The method takes 2 arguments. Again, the first one is the data from Firestore for this particular document.
logic
documentation
programming
And the second one is a Boolean, which tells us whether or not this widget is actively swipe to in the page view.
The next thing we'll do is define a few variables here, which will be different depending on whether or not the widget is active. These are the properties that we want to animate. For example, when the widget is active, we want to give it a blur and an offset.
animation
But if the widget is not active, then we just want to set those values to 0.
And then we'll decrease the margin on the top when the widget is active so it appears taller when it's in the middle. The really cool thing about this is we can make all these animations happen automatically by using an animated container. Are. Flutter will automatically perform an animation when any of the properties on this widget change. We just need to provide it with a duration, which we'll set at 500 milliseconds and also a timing curve. You can select any curve you want here. They all look pretty good. The next thing we'll do is set the margin. And notice that the top margin is using our animated property while the bottom and right are just hard coded as integer values. From there, we'll define the box decoration for this container.
animation
geometry
We can give it rounded edges by defining a border radius, then setting a circular radius of around 20.
The next thing we'll do is define a background image as a decoration image, and we'll have it fit the entire height and width of the viewport by calling box fit cover. The image itself will be loaded over the Internet based on that image's URL. In Flutter, we can do that with the network image widget, then we'll pass in the image URL that we get from the Firestore database. And the last piece of decoration that we wanna add here is a box shadow. Will want to animate the radius and the offset so the card appears to levitate off the screen when it becomes active in the middle. And because we're using an animated container, we don't need an animation controller, anything like that, Flutter handles all that stuff under the hood for us automatically. When it comes to animation, it really doesn't get any easier than that. And I almost forgot, you'll also want to add a child widget down here as well that includes the text to show the text from Firestore in the middle. At this point, you should have the stories pages displaying correctly. Our last step is to set up the buttons that allow the user to filter between the different pages. Will be reusing the same button logic over and over again, so I'll define a method called build button that takes a tag as its argument.
animation
blogging
visualization
graphic design
toys
If that tag is already applied, then I'm going to go ahead and color that button purple. Otherwise, it'll be colored white. The button text itself will just be the tag plus a hashtag. Then when pressed, it will call the query DB method that we defined earlier. And again that will call a set state on the widget as well as change the stream that we're listening to from Firestore.
Now that we have that logic in place we'll go ahead and actually build out the tag page. It starts with a container. And then inside that container, we have a column. Then we'll go ahead and align the children in that column in the center vertically and then to the left on the horizontal axis.
logic
Then we'll add a couple of text widgets, and then we'll build out the buttons that we need for the various tags.
I'm just going to hard code the tag names in there for now. But in a real world app, you would most likely query those from the database because the user is going to be generating those tags dynamically. I'm gonna go ahead and wrap things up there. If this video helped you, please can subscribe. And if you want even more content, consider becoming a pro member at Fireship I o. That'll give you access to my full Flutter course which will be available in the next couple weeks.
youtube
databases
streaming
Thanks for watching, and I will talk to you soon.
One of the most popular showcase apps for Flutter is Reflectly. It's an AI powered journal, and the developers did a really awesome job designing the UI. In today's video, we'll build our own animated slideshow from scratch using this app as our inspiration. Not only will it have this fluid transition between pages, but it will also be wired up with Firestore so we can filter the data on the back end. And we'll do the entire thing in about a 100 lines of code. If you're new to the channel, like and subscribe and you can find the full source code on FireShip. Io. Let's take a closer look at the demo. When the user swipes, they can see a preview of the next page on the right and a preview of the previous page on the left. The active page in the middle will animate into the view by increasing its height and also add a box shadow to give it depth. The buttons on the first card will actually make a query to Firestore so we can filter the number of pages that are shown in the list. Everything stays synced up in real time, so if we want to add another page, all we do is add some data to Firestore, and it's automatically reflected in the UI. We're going to look at a handful of important widgets here, but the single most important one is the page view. Too. It's a built in widget that comes with gesture detection and animation, allowing the user to swipe between a linear set of pages or widgets. I want to show you how the page view works before we get into the main feature. When When we jump into a basic Flutter app, the first thing we'll do is set up a page controller. That controller allows you to navigate between pages manually and also gives you information about the state of the page view. For a basic slider, you actually don't really need to do anything with the controller. You just need to pass it in as an argument to the page view widget in the widget tree. The next thing we'll do is add the page view widget as the body of our scaffold. And a cool little side note is that you can control the scroll direction as either vertical or horizontal. From there, we'll pass star controller, and then we'll define an array of children widgets. I'm just going to hard code a few containers in here to show you the effect. Because we have the scroll direction set to vertical, we can swipe from top to bottom to navigate between the pages. So now that you know how a page view works, you can go ahead and delete all that code, and we're going to build something a lot more advanced. At this point, I'm assuming that you have Firebase installed in your Flutter project. If not, you'll want to stop right here and follow the official Flutter fire setup guide. Back in the code, you'll see that I'm importing Firestore, and then I have our Firestore slideshow set up as the body of the scaffold. And then I have an empty Stateful widget. The Stateful widget will encapsulate this entire feature. Let's start by taking a look at the different properties that we'll need on this widget. The first one is our page controller, and we have an important option here called viewport fraction, which I've set to 0.8. By default, each page will take up 100% of the viewport, but setting that fraction to 0.8 will allow the previous and next page to overflow a little bit into the screen. The next thing we'll do is set up the instance of Firestore so we can interact with the back end database. Then we'll define a stream of slides. This will be the actual data from the database that we read to display the pages in the page view, and then we'll allow the user to filter them based on a certain tag. And we'll just set the default tag to favorites. And the last thing we'll do is keep track of the current page index so we can avoid unnecessary renders and just optimize performance. Now there are two reasons for us to rerender this widget. The first one is if the underlying data changes. So on a knit state, we'll query the database, but then the user will also have the option to click a button to make a new query, which will then cause us to rerender the widget. And then we'll also set up a listener on the actual page controller itself, and this fires an event anytime the state of the page controller changes. It'll give you the exact fraction of the page that's available in the view, but we'll go ahead and round that to an integer because we really only care about a will page change that we can animate into the view by adding a box shadow and increasing the height. We'll go ahead and call set state when the active page changes, and then I'll show you how to build the animation in a few minutes here. The next thing we'll wanna focus on is getting our actual data from Firestore. When the component is first initialized, we'll query the database using the default tag of favorites. Now before we implement the code, let's take a look at the database. We have a collection of stories and then we have a few documents in that collection. Each document contains the data for a page. So it has a background image and a title, which are both strings. And then we have a property called tags, which is an array of strings. We're going to query Firestore based on the data in this array. For For example, if the user clicks on the happy tag, it will only query the documents that have the happy tag in the array in the database. That gives us a very easy way to model tags on the back end, but just keep in mind that you can only query by 1 tag at a time. So that's an important limitation to think about if you need to filter by multiple tags at the same time. We'll define a method called query DB that takes a tag as its argument. We'll set up the query by first making a reference to the stories collection, that we call where tags array contains the tag that's passed in as the argument. That's all it takes to query the database. And now that we have that query, we want to map it to the tool, data payload that's in the database. For that, we have to take the stream of document snapshots and then map it down to the document data for each document in that array. First, we call map on the stream and then we call map on the list that's contained inside that stream. And then we call doc data, so we have the actual raw data from the database. And the last thing I wanna do is call set state on the stateful widget so we can update the active tag when this method is called. Now we have everything in place to start implementing the widgets build method. In. We'll start by returning a stream builder that takes these slides as its stream argument, and then we'll set some initial data as an empty array. The stream builder allows the widget to react in real time if any of the back end data changes. We'll call this builder method with a snapshot of the stream whenever a change occurs. Inside the builder, I'm going to define a variable called slide list, which is the exact data that we have contained in the Firestore database. After that, I'm going to set up our page view widget, but instead of passing it a static array of children, I'm going to use its builder method. The builder method will only render the pages that are actually visible on the fly. So that means it can scale up to an infinite number of pages depending on how much data you have in Firestore. We'll first need to pass in our page controller, and then we'll set the item count to the slide list length. And we'll add one to it, and that extra one represents the initial page of links that will show as the first page in the page view. Now this takes a builder method that provides the context and the current index of the visible page. We have 2 different types of pages we wanna display here. The first one is that initial tag page, which allows the user to click on buttons to filter the number of slides in the page view. We'll show that if the visible index equals 0. Otherwise, we want to build one of the animated story pages. And for that, we need to determine if that particular page is active. We're already keeping track of the current page on this widget, so So all we have to do is compare the current index to the current page. And then we'll extract the logic out to another build function called build story page, and it will take the raw data as the first argument and in the Boolean active value as its second argument. That takes care of the logic for the slideshow as a whole, but now we need to build out the individual pages. We'll build the story page first, which is just a container with an image background, some rounded corners, and a box shadow. The method takes 2 arguments. Again, the first one is the data from Firestore for this particular document. And the second one is a Boolean, which tells us whether or not this widget is actively swipe to in the page view. The next thing we'll do is define a few variables here, which will be different depending on whether or not the widget is active. These are the properties that we want to animate. For example, when the widget is active, we want to give it a blur and an offset. But if the widget is not active, then we just want to set those values to 0. And then we'll decrease the margin on the top when the widget is active so it appears taller when it's in the middle. The really cool thing about this is we can make all these animations happen automatically by using an animated container. Are. Flutter will automatically perform an animation when any of the properties on this widget change. We just need to provide it with a duration, which we'll set at 500 milliseconds and also a timing curve. You can select any curve you want here. They all look pretty good. The next thing we'll do is set the margin. And notice that the top margin is using our animated property while the bottom and right are just hard coded as integer values. From there, we'll define the box decoration for this container. We can give it rounded edges by defining a border radius, then setting a circular radius of around 20. The next thing we'll do is define a background image as a decoration image, and we'll have it fit the entire height and width of the viewport by calling box fit cover. The image itself will be loaded over the Internet based on that image's URL. In Flutter, we can do that with the network image widget, then we'll pass in the image URL that we get from the Firestore database. And the last piece of decoration that we wanna add here is a box shadow. Will want to animate the radius and the offset so the card appears to levitate off the screen when it becomes active in the middle. And because we're using an animated container, we don't need an animation controller, anything like that, Flutter handles all that stuff under the hood for us automatically. When it comes to animation, it really doesn't get any easier than that. And I almost forgot, you'll also want to add a child widget down here as well that includes the text to show the text from Firestore in the middle. At this point, you should have the stories pages displaying correctly. Our last step is to set up the buttons that allow the user to filter between the different pages. Will be reusing the same button logic over and over again, so I'll define a method called build button that takes a tag as its argument. If that tag is already applied, then I'm going to go ahead and color that button purple. Otherwise, it'll be colored white. The button text itself will just be the tag plus a hashtag. Then when pressed, it will call the query DB method that we defined earlier. And again that will call a set state on the widget as well as change the stream that we're listening to from Firestore. Now that we have that logic in place we'll go ahead and actually build out the tag page. It starts with a container. And then inside that container, we have a column. Then we'll go ahead and align the children in that column in the center vertically and then to the left on the horizontal axis. Then we'll add a couple of text widgets, and then we'll build out the buttons that we need for the various tags. I'm just going to hard code the tag names in there for now. But in a real world app, you would most likely query those from the database because the user is going to be generating those tags dynamically. I'm gonna go ahead and wrap things up there. If this video helped you, please can subscribe. And if you want even more content, consider becoming a pro member at Fireship I o. That'll give you access to my full Flutter course which will be available in the next couple weeks. Thanks for watching, and I will talk to you soon.
One
one
of
of
the
the
most
most
popular
popular
showcase
showcase
apps
apps
for
for
Flutter
flutter
is
is
Reflectly.
reflectly
It's
it's
an
an
AI
ai
powered
powered
journal,
journal
and
and
the
the
developers
developers
did
did
a
a
really
really
awesome
awesome
job
job
designing
designing
the
the
UI.
ui
In
in
today's
today's
video,
video
we'll
we'll
build
build
our
our
own
own
animated
animated
slideshow
slideshow
from
from
scratch
scratch
using
using
this
this
app
app
as
as
our
our
inspiration.
inspiration
Not
not
only
only
will
will
it
it
have
have
this
this
fluid
fluid
transition
transition
between
between
pages,
pages
but
but
it
it
will
will
also
also
be
be
wired
wired
up
up
with
with
Firestore
firestore
so
so
we
we
can
can
filter
filter
the
the
data
data
on
on
the
the
back
back
end.
end
And
and
we'll
we'll
do
do
the
the
entire
entire
thing
thing
in
in
about
about
a
a
100
100
lines
lines
of
of
code.
code
If
if
you're
you're
new
new
to
to
the
the
channel,
channel
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
Let's
let's
take
take
a
a
closer
closer
look
look
at
at
the
the
demo.
demo
When
when
the
the
user
user
swipes,
swipes
they
they
can
can
see
see
a
a
preview
preview
of
of
the
the
next
next
page
page
on
on
the
the
right
right
and
and
a
a
preview
preview
of
of
the
the
previous
previous
page
page
on
on
the
the
left.
left
The
the
active
active
page
page
in
in
the
the
middle
middle
will
will
animate
animate
into
into
the
the
view
view
by
by
increasing
increasing
its
its
height
height
and
and
also
also
add
add
a
a
box
box
shadow
shadow
to
to
give
give
it
it
depth.
depth
The
the
buttons
buttons
on
on
the
the
first
first
card
card
will
will
actually
actually
make
make
a
a
query
query
to
to
Firestore
firestore
so
so
we
we
can
can
filter
filter
the
the
number
number
of
of
pages
pages
that
that
are
are
shown
shown
in
in
the
the
list.
list
Everything
everything
stays
stays
synced
synced
up
up
in
in
real
real
time,
time
so
so
if
if
we
we
want
want
to
to
add
add
another
another
page,
page
all
all
we
we
do
do
is
is
add
add
some
some
data
data
to
to
Firestore,
firestore
and
and
it's
it's
automatically
automatically
reflected
reflected
in
in
the
the
UI.
ui
We're
we're
going
going
to
to
look
look
at
at
a
a
handful
handful
of
of
important
important
widgets
widgets
here,
here
but
but
the
the
single
single
most
most
important
important
one
one
is
is
the
the
page
page
view.
view
Too.
too
It's
it's
a
a
built
built
in
in
widget
widget
that
that
comes
comes
with
with
gesture
gesture
detection
detection
and
and
animation,
animation
allowing
allowing
the
the
user
user
to
to
swipe
swipe
between
between
a
a
linear
linear
set
set
of
of
pages
pages
or
or
widgets.
widgets
I
i
want
want
to
to
show
show
you
you
how
how
the
the
page
page
view
view
works
works
before
before
we
we
get
get
into
into
the
the
main
main
feature.
feature
When
when
When
when
we
we
jump
jump
into
into
a
a
basic
basic
Flutter
flutter
app,
app
the
the
first
first
thing
thing
we'll
we'll
do
do
is
is
set
set
up
up
a
a
page
page
controller.
controller
That
that
controller
controller
allows
allows
you
you
to
to
navigate
navigate
between
between
pages
pages
manually
manually
and
and
also
also
gives
gives
you
you
information
information
about
about
the
the
state
state
of
of
the
the
page
page
view.
view
For
for
a
a
basic
basic
slider,
slider
you
you
actually
actually
don't
don't
really
really
need
need
to
to
do
do
anything
anything
with
with
the
the
controller.
controller
You
you
just
just
need
need
to
to
pass
pass
it
it
in
in
as
as
an
an
argument
argument
to
to
the
the
page
page
view
view
widget
widget
in
in
the
the
widget
widget
tree.
tree
The
the
next
next
thing
thing
we'll
we'll
do
do
is
is
add
add
the
the
page
page
view
view
widget
widget
as
as
the
the
body
body
of
of
our
our
scaffold.
scaffold
And
and
a
a
cool
cool
little
little
side
side
note
note
is
is
that
that
you
you
can
can
control
control
the
the
scroll
scroll
direction
direction
as
as
either
either
vertical
vertical
or
or
horizontal.
horizontal
From
from
there,
there
we'll
we'll
pass
pass
star
star
controller,
controller
and
and
then
then
we'll
we'll
define
define
an
an
array
array
of
of
children
children
widgets.
widgets
I'm
i'm
just
just
going
going
to
to
hard
hard
code
code
a
a
few
few
containers
containers
in
in
here
here
to
to
show
show
you
you
the
the
effect.
effect
Because
because
we
we
have
have
the
the
scroll
scroll
direction
direction
set
set
to
to
vertical,
vertical
we
we
can
can
swipe
swipe
from
from
top
top
to
to
bottom
bottom
to
to
navigate
navigate
between
between
the
the
pages.
pages
So
so
now
now
that
that
you
you
know
know
how
how
a
a
page
page
view
view
works,
works
you
you
can
can
go
go
ahead
ahead
and
and
delete
delete
all
all
that
that
code,
code
and
and
we're
we're
going
going
to
to
build
build
something
something
a
a
lot
lot
more
more
advanced.
advanced
At
at
this
this
point,
point
I'm
i'm
assuming
assuming
that
that
you
you
have
have
Firebase
firebase
installed
installed
in
in
your
your
Flutter
flutter
project.
project
If
if
not,
not
you'll
you'll
want
want
to
to
stop
stop
right
right
here
here
and
and
follow
follow
the
the
official
official
Flutter
flutter
fire
fire
setup
setup
guide.
guide
Back
back
in
in
the
the
code,
code
you'll
you'll
see
see
that
that
I'm
i'm
importing
importing
Firestore,
firestore
and
and
then
then
I
i
have
have
our
our
Firestore
firestore
slideshow
slideshow
set
set
up
up
as
as
the
the
body
body
of
of
the
the
scaffold.
scaffold
And
and
then
then
I
i
have
have
an
an
empty
empty
Stateful
stateful
widget.
widget
The
the
Stateful
stateful
widget
widget
will
will
encapsulate
encapsulate
this
this
entire
entire
feature.
feature
Let's
let's
start
start
by
by
taking
taking
a
a
look
look
at
at
the
the
different
different
properties
properties
that
that
we'll
we'll
need
need
on
on
this
this
widget.
widget
The
the
first
first
one
one
is
is
our
our
page
page
controller,
controller
and
and
we
we
have
have
an
an
important
important
option
option
here
here
called
called
viewport
viewport
fraction,
fraction
which
which
I've
i've
set
set
to
to
0.8.
0.8
By
by
default,
default
each
each
page
page
will
will
take
take
up
up
100%
100%
of
of
the
the
viewport,
viewport
but
but
setting
setting
that
that
fraction
fraction
to
to
0.8
0.8
will
will
allow
allow
the
the
previous
previous
and
and
next
next
page
page
to
to
overflow
overflow
a
a
little
little
bit
bit
into
into
the
the
screen.
screen
The
the
next
next
thing
thing
we'll
we'll
do
do
is
is
set
set
up
up
the
the
instance
instance
of
of
Firestore
firestore
so
so
we
we
can
can
interact
interact
with
with
the
the
back
back
end
end
database.
database
Then
then
we'll
we'll
define
define
a
a
stream
stream
of
of
slides.
slides
This
this
will
will
be
be
the
the
actual
actual
data
data
from
from
the
the
database
database
that
that
we
we
read
read
to
to
display
display
the
the
pages
pages
in
in
the
the
page
page
view,
view
and
and
then
then
we'll
we'll
allow
allow
the
the
user
user
to
to
filter
filter
them
them
based
based
on
on
a
a
certain
certain
tag.
tag
And
and
we'll
we'll
just
just
set
set
the
the
default
default
tag
tag
to
to
favorites.
favorites
And
and
the
the
last
last
thing
thing
we'll
we'll
do
do
is
is
keep
keep
track
track
of
of
the
the
current
current
page
page
index
index
so
so
we
we
can
can
avoid
avoid
unnecessary
unnecessary
renders
renders
and
and
just
just
optimize
optimize
performance.
performance
Now
now
there
there
are
are
two
two
reasons
reasons
for
for
us
us
to
to
rerender
rerender
this
this
widget.
widget
The
the
first
first
one
one
is
is
if
if
the
the
underlying
underlying
data
data
changes.
changes
So
so
on
on
a
a
knit
knit
state,
state
we'll
we'll
query
query
the
the
database,
database
but
but
then
then
the
the
user
user
will
will
also
also
have
have
the
the
option
option
to
to
click
click
a
a
button
button
to
to
make
make
a
a
new
new
query,
query
which
which
will
will
then
then
cause
cause
us
us
to
to
rerender
rerender
the
the
widget.
widget
And
and
then
then
we'll
we'll
also
also
set
set
up
up
a
a
listener
listener
on
on
the
the
actual
actual
page
page
controller
controller
itself,
itself
and
and
this
this
fires
fires
an
an
event
event
anytime
anytime
the
the
state
state
of
of
the
the
page
page
controller
controller
changes.
changes
It'll
it'll
give
give
you
you
the
the
exact
exact
fraction
fraction
of
of
the
the
page
page
that's
that's
available
available
in
in
the
the
view,
view
but
but
we'll
we'll
go
go
ahead
ahead
and
and
round
round
that
that
to
to
an
an
integer
integer
because
because
we
we
really
really
only
only
care
care
about
about
a
a
will
will
page
page
change
change
that
that
we
we
can
can
animate
animate
into
into
the
the
view
view
by
by
adding
adding
a
a
box
box
shadow
shadow
and
and
increasing
increasing
the
the
height.
height
We'll
we'll
go
go
ahead
ahead
and
and
call
call
set
set
state
state
when
when
the
the
active
active
page
page
changes,
changes
and
and
then
then
I'll
i'll
show
show
you
you
how
how
to
to
build
build
the
the
animation
animation
in
in
a
a
few
few
minutes
minutes
here.
here
The
the
next
next
thing
thing
we'll
we'll
wanna
wanna
focus
focus
on
on
is
is
getting
getting
our
our
actual
actual
data
data
from
from
Firestore.
firestore
When
when
the
the
component
component
is
is
first
first
initialized,
initialized
we'll
we'll
query
query
the
the
database
database
using
using
the
the
default
default
tag
tag
of
of
favorites.
favorites
Now
now
before
before
we
we
implement
implement
the
the
code,
code
let's
let's
take
take
a
a
look
look
at
at
the
the
database.
database
We
we
have
have
a
a
collection
collection
of
of
stories
stories
and
and
then
then
we
we
have
have
a
a
few
few
documents
documents
in
in
that
that
collection.
collection
Each
each
document
document
contains
contains
the
the
data
data
for
for
a
a
page.
page
So
so
it
it
has
has
a
a
background
background
image
image
and
and
a
a
title,
title
which
which
are
are
both
both
strings.
strings
And
and
then
then
we
we
have
have
a
a
property
property
called
called
tags,
tags
which
which
is
is
an
an
array
array
of
of
strings.
strings
We're
we're
going
going
to
to
query
query
Firestore
firestore
based
based
on
on
the
the
data
data
in
in
this
this
array.
array
For
for
For
for
example,
example
if
if
the
the
user
user
clicks
clicks
on
on
the
the
happy
happy
tag,
tag
it
it
will
will
only
only
query
query
the
the
documents
documents
that
that
have
have
the
the
happy
happy
tag
tag
in
in
the
the
array
array
in
in
the
the
database.
database
That
that
gives
gives
us
us
a
a
very
very
easy
easy
way
way
to
to
model
model
tags
tags
on
on
the
the
back
back
end,
end
but
but
just
just
keep
keep
in
in
mind
mind
that
that
you
you
can
can
only
only
query
query
by
by
1
1
tag
tag
at
at
a
a
time.
time
So
so
that's
that's
an
an
important
important
limitation
limitation
to
to
think
think
about
about
if
if
you
you
need
need
to
to
filter
filter
by
by
multiple
multiple
tags
tags
at
at
the
the
same
same
time.
time
We'll
we'll
define
define
a
a
method
method
called
called
query
query
DB
db
that
that
takes
takes
a
a
tag
tag
as
as
its
its
argument.
argument
We'll
we'll
set
set
up
up
the
the
query
query
by
by
first
first
making
making
a
a
reference
reference
to
to
the
the
stories
stories
collection,
collection
that
that
we
we
call
call
where
where
tags
tags
array
array
contains
contains
the
the
tag
tag
that's
that's
passed
passed
in
in
as
as
the
the
argument.
argument
That's
that's
all
all
it
it
takes
takes
to
to
query
query
the
the
database.
database
And
and
now
now
that
that
we
we
have
have
that
that
query,
query
we
we
want
want
to
to
map
map
it
it
to
to
the
the
tool,
tool
data
data
payload
payload
that's
that's
in
in
the
the
database.
database
For
for
that,
that
we
we
have
have
to
to
take
take
the
the
stream
stream
of
of
document
document
snapshots
snapshots
and
and
then
then
map
map
it
it
down
down
to
to
the
the
document
document
data
data
for
for
each
each
document
document
in
in
that
that
array.
array
First,
first
we
we
call
call
map
map
on
on
the
the
stream
stream
and
and
then
then
we
we
call
call
map
map
on
on
the
the
list
list
that's
that's
contained
contained
inside
inside
that
that
stream.
stream
And
and
then
then
we
we
call
call
doc
doc
data,
data
so
so
we
we
have
have
the
the
actual
actual
raw
raw
data
data
from
from
the
the
database.
database
And
and
the
the
last
last
thing
thing
I
i
wanna
wanna
do
do
is
is
call
call
set
set
state
state
on
on
the
the
stateful
stateful
widget
widget
so
so
we
we
can
can
update
update
the
the
active
active
tag
tag
when
when
this
this
method
method
is
is
called.
called
Now
now
we
we
have
have
everything
everything
in
in
place
place
to
to
start
start
implementing
implementing
the
the
widgets
widgets
build
build
method.
method
In.
in
We'll
we'll
start
start
by
by
returning
returning
a
a
stream
stream
builder
builder
that
that
takes
takes
these
these
slides
slides
as
as
its
its
stream
stream
argument,
argument
and
and
then
then
we'll
we'll
set
set
some
some
initial
initial
data
data
as
as
an
an
empty
empty
array.
array
The
the
stream
stream
builder
builder
allows
allows
the
the
widget
widget
to
to
react
react
in
in
real
real
time
time
if
if
any
any
of
of
the
the
back
back
end
end
data
data
changes.
changes
We'll
we'll
call
call
this
this
builder
builder
method
method
with
with
a
a
snapshot
snapshot
of
of
the
the
stream
stream
whenever
whenever
a
a
change
change
occurs.
occurs
Inside
inside
the
the
builder,
builder
I'm
i'm
going
going
to
to
define
define
a
a
variable
variable
called
called
slide
slide
list,
list
which
which
is
is
the
the
exact
exact
data
data
that
that
we
we
have
have
contained
contained
in
in
the
the
Firestore
firestore
database.
database
After
after
that,
that
I'm
i'm
going
going
to
to
set
set
up
up
our
our
page
page
view
view
widget,
widget
but
but
instead
instead
of
of
passing
passing
it
it
a
a
static
static
array
array
of
of
children,
children
I'm
i'm
going
going
to
to
use
use
its
its
builder
builder
method.
method
The
the
builder
builder
method
method
will
will
only
only
render
render
the
the
pages
pages
that
that
are
are
actually
actually
visible
visible
on
on
the
the
fly.
fly
So
so
that
that
means
means
it
it
can
can
scale
scale
up
up
to
to
an
an
infinite
infinite
number
number
of
of
pages
pages
depending
depending
on
on
how
how
much
much
data
data
you
you
have
have
in
in
Firestore.
firestore
We'll
we'll
first
first
need
need
to
to
pass
pass
in
in
our
our
page
page
controller,
controller
and
and
then
then
we'll
we'll
set
set
the
the
item
item
count
count
to
to
the
the
slide
slide
list
list
length.
length
And
and
we'll
we'll
add
add
one
one
to
to
it,
it
and
and
that
that
extra
extra
one
one
represents
represents
the
the
initial
initial
page
page
of
of
links
links
that
that
will
will
show
show
as
as
the
the
first
first
page
page
in
in
the
the
page
page
view.
view
Now
now
this
this
takes
takes
a
a
builder
builder
method
method
that
that
provides
provides
the
the
context
context
and
and
the
the
current
current
index
index
of
of
the
the
visible
visible
page.
page
We
we
have
have
2
2
different
different
types
types
of
of
pages
pages
we
we
wanna
wanna
display
display
here.
here
The
the
first
first
one
one
is
is
that
that
initial
initial
tag
tag
page,
page
which
which
allows
allows
the
the
user
user
to
to
click
click
on
on
buttons
buttons
to
to
filter
filter
the
the
number
number
of
of
slides
slides
in
in
the
the
page
page
view.
view
We'll
we'll
show
show
that
that
if
if
the
the
visible
visible
index
index
equals
equals
0.
0
Otherwise,
otherwise
we
we
want
want
to
to
build
build
one
one
of
of
the
the
animated
animated
story
story
pages.
pages
And
and
for
for
that,
that
we
we
need
need
to
to
determine
determine
if
if
that
that
particular
particular
page
page
is
is
active.
active
We're
we're
already
already
keeping
keeping
track
track
of
of
the
the
current
current
page
page
on
on
this
this
widget,
widget
so
so
So
so
all
all
we
we
have
have
to
to
do
do
is
is
compare
compare
the
the
current
current
index
index
to
to
the
the
current
current
page.
page
And
and
then
then
we'll
we'll
extract
extract
the
the
logic
logic
out
out
to
to
another
another
build
build
function
function
called
called
build
build
story
story
page,
page
and
and
it
it
will
will
take
take
the
the
raw
raw
data
data
as
as
the
the
first
first
argument
argument
and
and
in
in
the
the
Boolean
boolean
active
active
value
value
as
as
its
its
second
second
argument.
argument
That
that
takes
takes
care
care
of
of
the
the
logic
logic
for
for
the
the
slideshow
slideshow
as
as
a
a
whole,
whole
but
but
now
now
we
we
need
need
to
to
build
build
out
out
the
the
individual
individual
pages.
pages
We'll
we'll
build
build
the
the
story
story
page
page
first,
first
which
which
is
is
just
just
a
a
container
container
with
with
an
an
image
image
background,
background
some
some
rounded
rounded
corners,
corners
and
and
a
a
box
box
shadow.
shadow
The
the
method
method
takes
takes
2
2
arguments.
arguments
Again,
again
the
the
first
first
one
one
is
is
the
the
data
data
from
from
Firestore
firestore
for
for
this
this
particular
particular
document.
document
And
and
the
the
second
second
one
one
is
is
a
a
Boolean,
boolean
which
which
tells
tells
us
us
whether
whether
or
or
not
not
this
this
widget
widget
is
is
actively
actively
swipe
swipe
to
to
in
in
the
the
page
page
view.
view
The
the
next
next
thing
thing
we'll
we'll
do
do
is
is
define
define
a
a
few
few
variables
variables
here,
here
which
which
will
will
be
be
different
different
depending
depending
on
on
whether
whether
or
or
not
not
the
the
widget
widget
is
is
active.
active
These
these
are
are
the
the
properties
properties
that
that
we
we
want
want
to
to
animate.
animate
For
for
example,
example
when
when
the
the
widget
widget
is
is
active,
active
we
we
want
want
to
to
give
give
it
it
a
a
blur
blur
and
and
an
an
offset.
offset
But
but
if
if
the
the
widget
widget
is
is
not
not
active,
active
then
then
we
we
just
just
want
want
to
to
set
set
those
those
values
values
to
to
0.
0
And
and
then
then
we'll
we'll
decrease
decrease
the
the
margin
margin
on
on
the
the
top
top
when
when
the
the
widget
widget
is
is
active
active
so
so
it
it
appears
appears
taller
taller
when
when
it's
it's
in
in
the
the
middle.
middle
The
the
really
really
cool
cool
thing
thing
about
about
this
this
is
is
we
we
can
can
make
make
all
all
these
these
animations
animations
happen
happen
automatically
automatically
by
by
using
using
an
an
animated
animated
container.
container
Are.
are
Flutter
flutter
will
will
automatically
automatically
perform
perform
an
an
animation
animation
when
when
any
any
of
of
the
the
properties
properties
on
on
this
this
widget
widget
change.
change
We
we
just
just
need
need
to
to
provide
provide
it
it
with
with
a
a
duration,
duration
which
which
we'll
we'll
set
set
at
at
500
500
milliseconds
milliseconds
and
and
also
also
a
a
timing
timing
curve.
curve
You
you
can
can
select
select
any
any
curve
curve
you
you
want
want
here.
here
They
they
all
all
look
look
pretty
pretty
good.
good
The
the
next
next
thing
thing
we'll
we'll
do
do
is
is
set
set
the
the
margin.
margin
And
and
notice
notice
that
that
the
the
top
top
margin
margin
is
is
using
using
our
our
animated
animated
property
property
while
while
the
the
bottom
bottom
and
and
right
right
are
are
just
just
hard
hard
coded
coded
as
as
integer
integer
values.
values
From
from
there,
there
we'll
we'll
define
define
the
the
box
box
decoration
decoration
for
for
this
this
container.
container
We
we
can
can
give
give
it
it
rounded
rounded
edges
edges
by
by
defining
defining
a
a
border
border
radius,
radius
then
then
setting
setting
a
a
circular
circular
radius
radius
of
of
around
around
20.
20
The
the
next
next
thing
thing
we'll
we'll
do
do
is
is
define
define
a
a
background
background
image
image
as
as
a
a
decoration
decoration
image,
image
and
and
we'll
we'll
have
have
it
it
fit
fit
the
the
entire
entire
height
height
and
and
width
width
of
of
the
the
viewport
viewport
by
by
calling
calling
box
box
fit
fit
cover.
cover
The
the
image
image
itself
itself
will
will
be
be
loaded
loaded
over
over
the
the
Internet
internet
based
based
on
on
that
that
image's
image's
URL.
url
In
in
Flutter,
flutter
we
we
can
can
do
do
that
that
with
with
the
the
network
network
image
image
widget,
widget
then
then
we'll
we'll
pass
pass
in
in
the
the
image
image
URL
url
that
that
we
we
get
get
from
from
the
the
Firestore
firestore
database.
database
And
and
the
the
last
last
piece
piece
of
of
decoration
decoration
that
that
we
we
wanna
wanna
add
add
here
here
is
is
a
a
box
box
shadow.
shadow
Will
will
want
want
to
to
animate
animate
the
the
radius
radius
and
and
the
the
offset
offset
so
so
the
the
card
card
appears
appears
to
to
levitate
levitate
off
off
the
the
screen
screen
when
when
it
it
becomes
becomes
active
active
in
in
the
the
middle.
middle
And
and
because
because
we're
we're
using
using
an
an
animated
animated
container,
container
we
we
don't
don't
need
need
an
an
animation
animation
controller,
controller
anything
anything
like
like
that,
that
Flutter
flutter
handles
handles
all
all
that
that
stuff
stuff
under
under
the
the
hood
hood
for
for
us
us
automatically.
automatically
When
when
it
it
comes
comes
to
to
animation,
animation
it
it
really
really
doesn't
doesn't
get
get
any
any
easier
easier
than
than
that.
that
And
and
I
i
almost
almost
forgot,
forgot
you'll
you'll
also
also
want
want
to
to
add
add
a
a
child
child
widget
widget
down
down
here
here
as
as
well
well
that
that
includes
includes
the
the
text
text
to
to
show
show
the
the
text
text
from
from
Firestore
firestore
in
in
the
the
middle.
middle
At
at
this
this
point,
point
you
you
should
should
have
have
the
the
stories
stories
pages
pages
displaying
displaying
correctly.
correctly
Our
our
last
last
step
step
is
is
to
to
set
set
up
up
the
the
buttons
buttons
that
that
allow
allow
the
the
user
user
to
to
filter
filter
between
between
the
the
different
different
pages.
pages
Will
will
be
be
reusing
reusing
the
the
same
same
button
button
logic
logic
over
over
and
and
over
over
again,
again
so
so
I'll
i'll
define
define
a
a
method
method
called
called
build
build
button
button
that
that
takes
takes
a
a
tag
tag
as
as
its
its
argument.
argument
If
if
that
that
tag
tag
is
is
already
already
applied,
applied
then
then
I'm
i'm
going
going
to
to
go
go
ahead
ahead
and
and
color
color
that
that
button
button
purple.
purple
Otherwise,
otherwise
it'll
it'll
be
be
colored
colored
white.
white
The
the
button
button
text
text
itself
itself
will
will
just
just
be
be
the
the
tag
tag
plus
plus
a
a
hashtag.
hashtag
Then
then
when
when
pressed,
pressed
it
it
will
will
call
call
the
the
query
query
DB
db
method
method
that
that
we
we
defined
defined
earlier.
earlier
And
and
again
again
that
that
will
will
call
call
a
a
set
set
state
state
on
on
the
the
widget
widget
as
as
well
well
as
as
change
change
the
the
stream
stream
that
that
we're
we're
listening
listening
to
to
from
from
Firestore.
firestore
Now
now
that
that
we
we
have
have
that
that
logic
logic
in
in
place
place
we'll
we'll
go
go
ahead
ahead
and
and
actually
actually
build
build
out
out
the
the
tag
tag
page.
page
It
it
starts
starts
with
with
a
a
container.
container
And
and
then
then
inside
inside
that
that
container,
container
we
we
have
have
a
a
column.
column
Then
then
we'll
we'll
go
go
ahead
ahead
and
and
align
align
the
the
children
children
in
in
that
that
column
column
in
in
the
the
center
center
vertically
vertically
and
and
then
then
to
to
the
the
left
left
on
on
the
the
horizontal
horizontal
axis.
axis
Then
then
we'll
we'll
add
add
a
a
couple
couple
of
of
text
text
widgets,
widgets
and
and
then
then
we'll
we'll
build
build
out
out
the
the
buttons
buttons
that
that
we
we
need
need
for
for
the
the
various
various
tags.
tags
I'm
i'm
just
just
going
going
to
to
hard
hard
code
code
the
the
tag
tag
names
names
in
in
there
there
for
for
now.
now
But
but
in
in
a
a
real
real
world
world
app,
app
you
you
would
would
most
most
likely
likely
query
query
those
those
from
from
the
the
database
database
because
because
the
the
user
user
is
is
going
going
to
to
be
be
generating
generating
those
those
tags
tags
dynamically.
dynamically
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
can
can
subscribe.
subscribe
And
and
if
if
you
you
want
want
even
even
more
more
content,
content
consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
Fireship
fireship
I
i
o.
o
That'll
that'll
give
give
you
you
access
access
to
to
my
my
full
full
Flutter
flutter
course
course
which
which
will
will
be
be
available
available
in
in
the
the
next
next
couple
couple
weeks.
weeks
Thanks
thanks
for
for
watching,
watching
and
and
I
i
will
will
talk
talk
to
to
you
you
soon.
soon
success
The speakers discuss creating a animated Flutter app by using a framework called Fir POS and setting up page views, events, and data filters. They emphasize the importance of setting up query DB to model tags and the need to filter by multiple tags at once. The process of creating a widget and building a data payload from Firchef is discussed, along with setting up buttons and color buttons for the widget. A Flutter course is also mentioned for the following week.
Reflectly-Inspired Animated Slideshow with Flutter + Firebase
One of the most popular showcase apps for Flutter is Reflectly. It's an AI powered journal, and the developers did a really awesome job designing the UI. In today's video, we'll build our own animated slideshow from scratch using this app as our inspiration. Not only will it have this fluid transition between pages, but it will also be wired up with Firestore so we can filter the data on the back end. And we'll do the entire thing in about a 100 lines of code. If you're new to the channel, like and subscribe and you can find the full source code on FireShip. Io. Let's take a closer look at the demo. When the user swipes, they can see a preview of the next page on the right and a preview of the previous page on the left. The active page in the middle will animate into the view by increasing its height and also add a box shadow to give it depth. The buttons on the first card will actually make a query to Firestore so we can filter the number of pages that are shown in the list. Everything stays synced up in real time, so if we want to add another page, all we do is add some data to Firestore, and it's automatically reflected in the UI. We're going to look at a handful of important widgets here, but the single most important one is the page view. Too. It's a built in widget that comes with gesture detection and animation, allowing the user to swipe between a linear set of pages or widgets. I want to show you how the page view works before we get into the main feature. When When we jump into a basic Flutter app, the first thing we'll do is set up a page controller. That controller allows you to navigate between pages manually and also gives you information about the state of the page view. For a basic slider, you actually don't really need to do anything with the controller. You just need to pass it in as an argument to the page view widget in the widget tree. The next thing we'll do is add the page view widget as the body of our scaffold. And a cool little side note is that you can control the scroll direction as either vertical or horizontal. From there, we'll pass star controller, and then we'll define an array of children widgets. I'm just going to hard code a few containers in here to show you the effect. Because we have the scroll direction set to vertical, we can swipe from top to bottom to navigate between the pages. So now that you know how a page view works, you can go ahead and delete all that code, and we're going to build something a lot more advanced. At this point, I'm assuming that you have Firebase installed in your Flutter project. If not, you'll want to stop right here and follow the official Flutter fire setup guide. Back in the code, you'll see that I'm importing Firestore, and then I have our Firestore slideshow set up as the body of the scaffold. And then I have an empty Stateful widget. The Stateful widget will encapsulate this entire feature. Let's start by taking a look at the different properties that we'll need on this widget. The first one is our page controller, and we have an important option here called viewport fraction, which I've set to 0.8. By default, each page will take up 100% of the viewport, but setting that fraction to 0.8 will allow the previous and next page to overflow a little bit into the screen. The next thing we'll do is set up the instance of Firestore so we can interact with the back end database. Then we'll define a stream of slides. This will be the actual data from the database that we read to display the pages in the page view, and then we'll allow the user to filter them based on a certain tag. And we'll just set the default tag to favorites. And the last thing we'll do is keep track of the current page index so we can avoid unnecessary renders and just optimize performance. Now there are two reasons for us to rerender this widget. The first one is if the underlying data changes. So on a knit state, we'll query the database, but then the user will also have the option to click a button to make a new query, which will then cause us to rerender the widget. And then we'll also set up a listener on the actual page controller itself, and this fires an event anytime the state of the page controller changes. It'll give you the exact fraction of the page that's available in the view, but we'll go ahead and round that to an integer because we really only care about a will page change that we can animate into the view by adding a box shadow and increasing the height. We'll go ahead and call set state when the active page changes, and then I'll show you how to build the animation in a few minutes here. The next thing we'll wanna focus on is getting our actual data from Firestore. When the component is first initialized, we'll query the database using the default tag of favorites. Now before we implement the code, let's take a look at the database. We have a collection of stories and then we have a few documents in that collection. Each document contains the data for a page. So it has a background image and a title, which are both strings. And then we have a property called tags, which is an array of strings. We're going to query Firestore based on the data in this array. For For example, if the user clicks on the happy tag, it will only query the documents that have the happy tag in the array in the database. That gives us a very easy way to model tags on the back end, but just keep in mind that you can only query by 1 tag at a time. So that's an important limitation to think about if you need to filter by multiple tags at the same time. We'll define a method called query DB that takes a tag as its argument. We'll set up the query by first making a reference to the stories collection, that we call where tags array contains the tag that's passed in as the argument. That's all it takes to query the database. And now that we have that query, we want to map it to the tool, data payload that's in the database. For that, we have to take the stream of document snapshots and then map it down to the document data for each document in that array. First, we call map on the stream and then we call map on the list that's contained inside that stream. And then we call doc data, so we have the actual raw data from the database. And the last thing I wanna do is call set state on the stateful widget so we can update the active tag when this method is called. Now we have everything in place to start implementing the widgets build method. In. We'll start by returning a stream builder that takes these slides as its stream argument, and then we'll set some initial data as an empty array. The stream builder allows the widget to react in real time if any of the back end data changes. We'll call this builder method with a snapshot of the stream whenever a change occurs. Inside the builder, I'm going to define a variable called slide list, which is the exact data that we have contained in the Firestore database. After that, I'm going to set up our page view widget, but instead of passing it a static array of children, I'm going to use its builder method. The builder method will only render the pages that are actually visible on the fly. So that means it can scale up to an infinite number of pages depending on how much data you have in Firestore. We'll first need to pass in our page controller, and then we'll set the item count to the slide list length. And we'll add one to it, and that extra one represents the initial page of links that will show as the first page in the page view. Now this takes a builder method that provides the context and the current index of the visible page. We have 2 different types of pages we wanna display here. The first one is that initial tag page, which allows the user to click on buttons to filter the number of slides in the page view. We'll show that if the visible index equals 0. Otherwise, we want to build one of the animated story pages. And for that, we need to determine if that particular page is active. We're already keeping track of the current page on this widget, so So all we have to do is compare the current index to the current page. And then we'll extract the logic out to another build function called build story page, and it will take the raw data as the first argument and in the Boolean active value as its second argument. That takes care of the logic for the slideshow as a whole, but now we need to build out the individual pages. We'll build the story page first, which is just a container with an image background, some rounded corners, and a box shadow. The method takes 2 arguments. Again, the first one is the data from Firestore for this particular document. And the second one is a Boolean, which tells us whether or not this widget is actively swipe to in the page view. The next thing we'll do is define a few variables here, which will be different depending on whether or not the widget is active. These are the properties that we want to animate. For example, when the widget is active, we want to give it a blur and an offset. But if the widget is not active, then we just want to set those values to 0. And then we'll decrease the margin on the top when the widget is active so it appears taller when it's in the middle. The really cool thing about this is we can make all these animations happen automatically by using an animated container. Are. Flutter will automatically perform an animation when any of the properties on this widget change. We just need to provide it with a duration, which we'll set at 500 milliseconds and also a timing curve. You can select any curve you want here. They all look pretty good. The next thing we'll do is set the margin. And notice that the top margin is using our animated property while the bottom and right are just hard coded as integer values. From there, we'll define the box decoration for this container. We can give it rounded edges by defining a border radius, then setting a circular radius of around 20. The next thing we'll do is define a background image as a decoration image, and we'll have it fit the entire height and width of the viewport by calling box fit cover. The image itself will be loaded over the Internet based on that image's URL. In Flutter, we can do that with the network image widget, then we'll pass in the image URL that we get from the Firestore database. And the last piece of decoration that we wanna add here is a box shadow. Will want to animate the radius and the offset so the card appears to levitate off the screen when it becomes active in the middle. And because we're using an animated container, we don't need an animation controller, anything like that, Flutter handles all that stuff under the hood for us automatically. When it comes to animation, it really doesn't get any easier than that. And I almost forgot, you'll also want to add a child widget down here as well that includes the text to show the text from Firestore in the middle. At this point, you should have the stories pages displaying correctly. Our last step is to set up the buttons that allow the user to filter between the different pages. Will be reusing the same button logic over and over again, so I'll define a method called build button that takes a tag as its argument. If that tag is already applied, then I'm going to go ahead and color that button purple. Otherwise, it'll be colored white. The button text itself will just be the tag plus a hashtag. Then when pressed, it will call the query DB method that we defined earlier. And again that will call a set state on the widget as well as change the stream that we're listening to from Firestore. Now that we have that logic in place we'll go ahead and actually build out the tag page. It starts with a container. And then inside that container, we have a column. Then we'll go ahead and align the children in that column in the center vertically and then to the left on the horizontal axis. Then we'll add a couple of text widgets, and then we'll build out the buttons that we need for the various tags. I'm just going to hard code the tag names in there for now. But in a real world app, you would most likely query those from the database because the user is going to be generating those tags dynamically. I'm gonna go ahead and wrap things up there. If this video helped you, please can subscribe. And if you want even more content, consider becoming a pro member at Fireship I o. That'll give you access to my full Flutter course which will be available in the next couple weeks. Thanks for watching, and I will talk to you soon.
The speakers discuss creating a animated Flutter app by using a framework called Fir POS and setting up page views, events, and data filters. They emphasize the importance of setting up query DB to model tags and the need to filter by multiple tags at once. The process of creating a widget and building a data payload from Firchef is discussed, along with setting up buttons and color buttons for the widget. A Flutter course is also mentioned for the following week.