Building scrolling experiences in Flutter | Workshop

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[MUSIC PLAYING] KATE LOVETT: Hi, there. Welcome. My name is Kate Lovett. And I'm a software engineer on the Flutter team at Google. Today, we're going to learn about scrolling UIs in Flutter. We'll be taking a simple scrolling UI and enhancing it to be a rich, interactive experience for our users. We'll even be diving into slivers, which may seem daunting at first. But stay with me and you will see that not only are slivers quite nice once you get to know them, they are powerful tools when applied to create custom scrolling UIs. If you have never written a Flutter app before, you may like to check out Writing Your First Flutter App before taking this workshop I'll be right here waiting for you when you come back. For those of you joining us on the live stream, remember to post your questions in the Q&A section. We have Flutter experts standing by to answer your questions. Or they may send them my way, so that we can explore them together. So when you are ready for our journey today, we'll be using DartPad. DartPad is an open source tool you can use to write Flutter applications without ever needing to download and install the Flutter SDK. It's a fantastic way to get started writing Dart code and experimenting with Flutter without any of the setup. We'll be using a special version of DartPad today as well-- one that will take us through this workshop one at a time. So when you're ready, join me at Flutter.dev/go/sliver-workshop. That's Flutter.dev/go/sliver-workshop. Are you here with me? Excellent. You should see a UI just like I have here on my screen. On the left, we have our instructions, which will guide us through each step of the workshop. I won't be reading directly from this pane the whole time. But I'll be staying on track with it as we go. On the right, we have two panes-- one with our code and the other with our output. It is here, when we press the Run button, that we will see our UI rendered. This is because Flutter doesn't just run on a mobile device. And it doesn't run on just a desktop machine, either. Flutter also runs on the web. So we can check out the result of our code here, just as we would on a device. A few more points of interest in our workspace that I like to call out-- in your top left corner, you'll see a Format button. That's handy for quickly tidying up our workspace as we go. You could also use the keyboard shortcut, Control+Shift+F. For more keyboard shortcuts, click the Keyboard icon in the bottom left corner of your screen. So let me just run our starter code here. And let's first take a look and see what we're starting out with. All right. Here, we have a simple weather application with the forecast for the next seven days. And it is scrollable, for some of our smaller screens. Our primary scrollable here is a single child scroll view that contains a column with all seven of our forecasts. Anything that scrolls in Flutter, like a single child scroll view, is really a sliver. If you have used a list view or a grid view in your applications, you have already worked with some slivers. These classes give us convenient ways to compose slivers, rather than working with them directly. And we'll dig into why they're different later on in this workshop. We also have a custom scroll behavior in our app. Scroll behaviors dictate how scrolling widgets look and feel in a Flutter app. By default, they adapt to the current platform, behaving a little differently depending on the machine or device you are using. This is so that every Flutter scrolling experience matches the native behavior your users expect on their devices. For the purposes of this workshop, we have a constant scroll behavior. So every one of us is having the same experience, regardless of the machine we are using while we're learning about the intricacies of slivers. Scroll behaviors are inherited. So if you'd like to learn more, check out our Inherited Widgets Workshop. OK. So where do we even start? Well, first, we will be looking at making our scrollable more efficient, before we add to our UI. Later, we'll dive into working directly with slivers. So let's get going and move on to step 2. OK. As we progress through this Codelab, keep an eye out for the to-dos. They will help us focus in on our area of work for the step. If you click on them here in the Analyzer pane, it will take you straight there. So the first thing that we would like to do here is we'd like to make our single child scroll view more efficient. But let's first talk about why this sometimes may not be the most efficient choice. Currently, our UI is pretty simple. The scrolling seven-day forecast is likely to fit on most screens. And the single child scroll view gives us an assurance that, on some of the smallest screens, we won't run out of room. What I mean by that is, if I remove the single child scroll view, we might end up overflowing our column like this. So I'm going to hide the Analyzer pane. And I'm going to make use of one of our handy shortcuts, Alt+Enter, or on my keyboard Option+Enter. This gives us a quick picker to make some modifications to our widgets. And I'm going to remove the single child scroll view. So now, we just have a column with our seven forecasts. And if I run this, we will see that we get a nasty render overflow error. Why is that, though? This is where we can see how the layout protocol of slivers differs from their relative, the box layout protocol. A column is laid out using box constraints. It has a height, and a width, and a position within the window. A column cannot lay out beyond the bounds of the window. When we wrap our column in a single child scroll view, we are essentially wrapping our column in a sliver. Slivers lay out using sliver constraints and use a sliver geometry. When working with slivers, the window pane we were constricted to previously becomes an infinite amount of space in the given axis. So we use language different from height, width, and position. As a sliver, we need to know things like how much of it is visible, and how far to the next sliver, and how far have we scrolled anyway. The answers to these questions allow us to lazily load slivers, meaning we only build the slivers we can see, and a little bit of the ones on either edge. This makes our scrolling more efficient, as we won't build any slivers we don't need to, since we can't actually see them. Since the single child scroll view is only one sliver, we aren't lazily loading our UI. Instead, as our column gets bigger and more complicated, all of its contents are being built. So before we add more to our UI, let's make this more efficient by using a list view instead. So I'm going to go ahead and close our Output pane. And in our instructions, this is our aim. We're going to replace our column instead with a list view using the Builder Constructor. This will allow us to build our cards on demand. So if I change this to a builder, I no longer want to provide all of my children. I want to build them using an item builder. I'm going to go ahead and get rid of this Map function and just change these parameters to what an item builder would provide us. That would involve a build context, as well as the current index that we are building for, all right? Down here, I no longer to need to cast all of my forecasts into a list or a column. So we can just clean that up and remove this. And lastly, before, I was getting all of my forecasts all at once. But now, I'm going to go ahead and get them on demand. So I'm going to go ahead and remove the forecasts and our little to-do, since we are resolving it here. And inside our Builder Function, I'm going to go ahead and retrieve our daily forecast on demand, just like we're building our cards on demand. I'm going to do that by accessing our mock server and getting it by ID [INAUDIBLE] index. OK, let's see how this looks when we run it. Well, instead of our render overflow, we're now back to the way that we were. Oh, it looks like I may have forgotten something. I actually have an assertion in my server code to make sure that I am not building beyond my seven forecasts. And it looks like I forgot to include my item count. There are only seven days in my forecast in the mock data that we're using. So I want to make sure that I include that. So let's try that again OK, we are back to looking the way we were before. But we've made a performance change. We are now only building our cards on demand. So Monday, Tuesday, Wednesday, those are only being built as we need them, as we're scrolling. So now that we're being efficient, let's go ahead and add to our UI. Our daily forecast object comes with an image. I think it would be great to add some context to our forecasts. So looking at our cards, we've been composing all of our information about our daily forecast using a list tile. This is a really handy widget that handles a lot of layout, and padding, and alignment for you. But looking at what we have, I think that we can handle this. So let's break this up into some rows and columns, and then find a way to integrate our image. What I'm going to do is I'm going to break this up into a row with our title and subtitle. Since they're stacked on top of one another, put them in a column. So let me close this so we have a little bit more space to work with. I'm going to change our list style to a row, which takes the list of children. And I'm going to copy-paste right out of our list tile parameters. The Analyzer's going to be unhappy with me for a moment. So do bear with me. I'm going to move the leading up here, and then take that away. I'm going to go ahead and move the trailing just after it. And let me see if I can resize this. And then in between, I'm going to place a column for our title and subtitle. Now, a column, just like a row, takes a list of children. And we're just going to go ahead and plug our title and subtitle from our former list tile right back in there. Take away parameters. It looks like we need a little bit of formatting help here. Easily solved. All right, so what we've done is we've taken away our list tiles. We've added a row with a column and pretty much aligned everything just the way it was in our list tile, right? Let's take a look and see how it turned out. Well, that is pretty close to the way the list tile put things together. We are missing some white space. And as many of you know, I'm sure padding is the secret cherry on top of most UIs. So let's just spruce this up a little bit with some white space. I'm going to go ahead and close this. And around our column, I'm going to put an expanded widget. This will force our column to take up the majority of the space in the row that it possibly can. So we'll get a similar effect to the tile that we had. Using our Option+Enter or Alt+Enter shortcut, I'm going to go ahead and wrap with a widget and make this one expanded. I'm also going to add some padding. So we'll add some padding around our tile here. And we might as well add it around our temperature as well, just for good measure, so everything has a nice bit of leeway around it. And there's one more thing that I forgot. In our column, we want to make sure that everything has that left justify that we originally had with the list tile. So I'm going to add a cross-axi alignment. And that'll be Start. OK, let's see if we're any closer, so we can start plugging in our pictures. Looking much better. Wow. And it really didn't take too much for us to get there. So I'd like to put an image behind our date. I think that would create a really nice effect to our UI. So the first thing that I'm going to do is I am going to go up here to where our date is. And I'm going to wrap it in a sized box. Just like so. I'm going to give it a height and a width of 200. I think that should be big enough. And then in order to place the image underneath my text, I'm going to use a stack. Now, in our shortcuts here, I'm going to choose a column, just because that'll make it a little easier to turn this into a stack because a stack takes a list of children. And from the beginning to the end, it stacks them one on top of each other. So before my text, I'll put an image. Our image is stored in our daily forecast at imageID. And then I'm also going to make sure that I set a fit so that the image can take advantage of the entire space that I've given it with that sized box and do the same for the stack. OK. Well, we have a sized box-- wait, comma there. We have a sized box with a stack, with a text on top of an image. Survey says, let's run this. All right, this is actually looking pretty interesting now. There are a couple adjustments that we can certainly make for the contrast. Monday looks a little scary. We'll have to pack an umbrella. So we definitely want to make sure that we can see this. So let's add a little bit more contrast by adding a decoration. Ultimately, I know that I can add as much as I like now, because we're being really efficient with our scrolling. So in order to make this a little bit better before we move on, let's make our text a little bit bigger. And let's add a decorated box around our image. OK. So we are going to add a decorated box. And for our decoration, I'm going to choose a box decoration. And I think it would be pretty neat if we could put in a gradient. That way, we could see the text and still see the image. So let's add a radial gradient. Just take the list of colors that it will transition over. And so I'm going to choose just two. We're going to do a dark gray, so that we can get that contrast that we're looking for, and a transparent color so that we can still see the image. All right. I think I'm missing one more thing, though. Since I want this decoration to be on top of my image, I have to make sure that I provide a position, as long as I can spell it. That will be a declaration position of foreground, so that it'll be on top of my image. Let's see if we can read our text a little bit better Oh, I forgot one more thing, didn't I? We have our radial gradient, as you can see. But our text is still up in the corner. The last thing I wanted to do was I wanted to add a center and place it right on top. Awesome. We have better contrast now. We have images. It's starting to look pretty nice, although our app bar does seem a bit lacking now, in my opinion. It's not nearly as exciting as the rest of the work we've been doing. Let's move on to the next step and see what we can do about that. OK, I'd like to use a more dynamic app bar. And we do have the Sliver App Bar available to us. But first, we're going to need to dive into working with slivers directly and set a few things up first. Let's see what our to-dos have for us. First, we want to add a custom scroll view. Slivers are contained within a scroll view, like a container. And the list view is already setting some of this up for us. So the first thing we need to do is create our own container. So up here in the body of our scaffold, I'm going to add a custom scroll view. A custom worldview doesn't take a child or a list of children. Instead, it takes a list of slivers. Now, our weekly forecast list is not a sliver yet. But we're going to handle that next. OK. So there we are. We now have a custom scroll view with a soon to be sliver weekly forecast list. So let's go on down here and talk about converting this to a sliver list. A sliver list, just like our list view, will lazily load our UI, just like we intended to when we transferred from a single child scroll view to a list view with the Builder Constructor. Now, a sliver list, however, instead of an item builder, needs to be provided a sliver child delegate. This delegate is responsible for providing us the children on demand so that the sliver list can lay them all out. And one type of sliver child delegate is a sliver child builder delegate, which expects a build context and an index. And look, we are already ready for this. We already have much of this set up. So the first thing that I'm going to do to make this transition as easy as possible is I'm just going to wrap the list view in a widget. And I am going to make this our sliver list. Now, instead of a child, we are going to provide our delegate. And instead of-- let me hide that Analyzer pane. Instead of a list view, we are going to provide our sliver child builder delegate, which does not take an item count. We'll get to that in a sec. And instead of an item builder, it takes a positional builder function. Look at that. The Analyzer doesn't seem to be disappointed in us. We just have to still account for that item count, since I have those assertions in place in the server. And in order to find where to put this item count, I'm going to show you a fun trick. Since our builder function is a required positional argument, we have to go ahead and place our child count, which is a named optional parameter, afterwards. So if I put my cursor right here, I can see that the curly brace is illuminated. And I can easily find where to pick up and continue adding my parameters. I'm going to provide a child count of 7. All right, let us run this and take a look. It's the same again. Again, we did not expect a visual difference here. Instead, we had changed to using different tools and different widgets to get the same result. And now that we are working directly with slivers, we can explore doing something like the Sliver App Bar to have a much more dynamic experience here at the top of our scroll view. So now that we are working directly with slivers-- hooray and congratulations to us-- let us move on to step 5, where we can start playing with the Sliver App Bar. OK. So I'm going to go ahead and close this. We want our Sliver App Bar to be at the top, just like we expect for any other normal app bar. So right here in our custom scroll view, above our weekly forecast list, is where I'm going to add it. Now, the Sliver App Bar shares a lot in common with the app bar that you may already know and love, including having a title and a background color. But let's just go ahead and move those over. That was a teal. Awesome. OK. So we now have a Sliver App Bar. What does it actually look like? Oh, it looks a lot like our app bar. This, at the top, being the bar that we have added right here in our scaffold, and our second one being our Sliver App Bar. But the big difference here is when I scroll, the Sliver App Bar scrolls away with the rest of my list. This is just one behavior of the Sliver App Bar. And there are many that we are about to explore. And so let's remove the app bar that we started with. Thank you very much. And let's start to explore the different behaviors of the Sliver App Bar. So I'm going to list them all out first. And then we'll explore them one by one. First, Sliver App Bars can be pinned. They can float in and out of view. It can also complete a snap animation. And they can have an expanded height. Let's just say 200. Let's look at these one at a time now. All right, we've pinned Sliver App Bar. This looks an awful lot like the bar that we started with. It stays at the top and lets the other rest of the content scroll underneath it, just like we would see in our other bar. OK, let's try floating. In this case, we'll see it scroll away. But at any point in the list, if I scroll back, it presents itself to me. This is really great for your users, if you want to present actions or shortcuts in the app bar without them going all the way back up to the top of the list. Floating app bars can also snap, which completes an animation that will open and close the bar as you scroll. So here we are again. It scrolls away. And this time, when I scroll back, it will present itself into full view without me scrolling it all the way back. Cool. Last on our list is expanded height. And this makes for a big app bar. OK. So we're still floating. We're still snapping. And now, we have a lot of extra real estate in our Sliver App Bar. As I scroll away though now, you'll see that this extra space collapses before it scrolls away. And since we're snapping, when I bring it back, it will all snap back into view. Just another really cool effect. There are so many different combinations that you can make with the Sliver App Bar. These are really just a few. If I go ahead and look at it just as a pinned app bar pinned with expanded height, I'm not quite sure what will happen then. Do you? Before, when we were pinned, the app bar didn't go anywhere. But since we have this expanded height, it becomes a collapsible space that then stays pinned. I like this going forward. So I'm going to keep it this way. But feel free to explore on your own and see which way you like best. Let's move on to step 6. Now that we have all this expanded height, I'd really like to take advantage of it. All right, the best way to take advantage of all this space in our Sliver App Bar now is using the flexible space bar. This is a widget that is designed to stretch and collapse its content as its container changes, which sounds just about perfect for our use case here. So I'm going to go ahead and add it to our Sliver App Bar. We can do this using flexible space. All right. We can move our title down here. And I'm going to keep our original title there because I'll show you why. [INAUDIBLE] And I also have a background image available. So let's add that there as well. I have this saved under header image. There we go. And again, I'm going to set a box for it so that we take advantage of all this space that we have available with boxfit.cover. All right, I think that checks all the boxes. Let's see what happens now when we use a flexible space. OK, we have a lovely image. We have some contrast issues we're going to have to address again. But as you can see, we have the title at the top is the original title of the Sliver App Bar. And I left it there so I can show you the cool effect that happens as we collapse this now. Our flexible space title will shrink to meet the other one as we go. And you'll notice that we have faded back into teal. And the image is doing this really neat parallax effect as we scroll. I think that's really great. And that's because flexible space bar has collapsed modes. Right now, by default, our flexible space bar is completing this parallax effect. But there are other ones available. So let's clean up a little bit here. We'll remove the title from our Sliver App Bar, since we don't need it anymore. And let's take a look at these collapse modes real quick. All right, so I'm in a flexible space bar, setting a collapse mode. Which ones do we have available? Well, there's parallax, which we know is the default, none, and pinned. So if it's pinned, we'll see that it will scroll just like the rest of our content in the list. I do like that parallax effect, though. So I think I'm going to stick with the default. But again, this is a choose your own adventure workshop. So pick which works best for you. OK. Let's take care of that contrast issue before we move on. And I'd like to do it in a way that we did similar to before. But instead of a radial gradient, let's see what else we have available to us. So around our image, we're going to put another decorated box with a lower case e. And we're again going to position in the foreground. And again, our decoration will be a box decoration. And this time, instead of a radial gradient, why don't we try a linear one? I think that would look really nice going right underneath that title so that we can see it clearly. Unlike our radial gradient, our linear gradient requires that we specify a beginning and an end that we're going to transition these colors towards. So to end up right underneath our title, I'm going to choose alignment.bottomcenter. And I'm going to transition all the way to the center. And then of course, we need to specify our colors. I really do like that teal that we've been sticking with up here as the header. So let's keep that and carry it here. Let me go transparent so that we can still see the image. All right. Let's see if that solves our contrast issue. Oh, there it is. Oh, wow, that looks really great. We can clearly see our image. And now, as it collapses and fades out, it transitions from teal to teal. I think that looks really nice. This is coming along very nicely from the simple UI that we started with. However, I think that there is a perfect little cherry on top that we can add. Let's explore that in step 7. All right, I have been holding back. There is one more behavior that the Sliver App Bar supports that I would like to show you. And it is called stretch. This is a common UI pattern that we see when folks want to refresh their data at the top of a list. And as you can see in our constant scroll behavior that we set at the very beginning of our workshop, we are using bouncing scroll physics. These scroll physics are common when you are using iOS platforms, for example. When you reach the end of your scroll view, you can overscroll and reveal this empty space. This extra space, though, can be taken advantage of by our Sliver App Bar. So let's see how to do that. I'm going to close this again. And it's quite simple. Just like panning, floating, and snapping, you can stretch to true. Now, of course, if you wanted to refresh your data, we exposed a callback for you. This is called on stretch trigger, which allows you to set an asynchronous callback. You can use this to tap our server and say, hey, get more data because the forecasts are constantly changing, no matter how hard we try. Now, we have a fake server here. So I can't actually do that. But I can click on the console just to confirm. This will be triggered by default when your user overscrolls to a distance of 100 pixels. But you can actually configure it to whatever distance you like. OK. So let's see what it looks like when we stretch. Open this up. Run it. Wow, instead of all that extra space when we over scroll, now our Sliver App Bar is taking advantage of it. And as you can see, there's something happening in the console. We've been printing every single time we over scroll far enough to trigger our callback. That is going to be super handy for updating our forecast. Now, as you can see, our image is scaling. And that is because, of course, the flexible space bar complements this feature by default. And it's actually using one of several stretch modes that are available. Let's take a look. Under flexible space bar, by default, we are seeing that it is using a stretch mode. It actually provides more than one. And by default, it is doing a zoom background effect. And this is what's creating that scaling. There we go. OK. If I take this away, we can see what the flexible space bar is doing for us out of the box. So without any stretch modes enabled, the image doesn't go anywhere. I don't really mind it because we have that linear gradient filling in the space. It's kind of neat. I'm going to leave it on, though. And let's just add all of them, all the bells and whistles for our last go-through. So the ones that are missing here are blurring the background, as well as fading the title as we scroll further away. So one last time with all of them turned on now, let's see what we have made. Again, we're collapsing our app bar. We're stretching our app bar. And it is fading, and blurring, and scaling. There are a lot of different things that you can do with the Sliver App Bar. And these are just a few of them we've touched on. We have really taken this far from where we started. Let's sum up in step 8. So, my friends, we have reached the end of our journey together. In this workshop, we have learned how to build scroll views efficiently using lazy loading for our scrollable. We converted our scroll view to work directly with slivers and explored the Sliver App Bar and how it's complemented by the flexible space bar. There are a lot more slivers to explore. And oftentimes, they are the same as their box counterparts. Where you may use a fade transition, you could use a sliver fade transition or padding versus sliver padding. All sliver widgets are prefixed with the word sliver. To learn more about these widgets and all of the Flutter widgets, you can visit Flutter.dev or dive into our API documentation link right down here. And you can also check out our Flutter YouTube channel for lots of tips, tricks, and tutorials on creating your next great user experience. I am so glad that you joined me and created what I think is a really fun app. So thank you very, very much. I hope that you are as excited now about scrolling as I am. And as always, I can't wait to see what you build. [MUSIC PLAYING]
Info
Channel: Flutter
Views: 120,578
Rating: undefined out of 5
Keywords: purpose: Educate, type: Conference Talk (Full production), pr_pr: Google I/O, Sliver layouts and scrolling, sliver layout, sliver layouts, sliver scrolling, sliver workshop, sliver scroll, sliver protocol, sliver, slivers, the sliver protocol, sliver development, sliver developer, flutter, dynamic layout, flutter sliver, slivers explained, flutter development, #GoogleIO, Google I/O, Google IO, Google developer conference, Google announcement, Google conference, Google
Id: YY-_yrZdjGc
Channel Id: undefined
Length: 37min 33sec (2253 seconds)
Published: Fri May 21 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.