[PEPPY MUSIC] MARY XIA: Good morning! Hey. My name is Mary. I'm a software engineer who works with Flutter. WILL LARCHE: And And I'm Will. I'm a software engineer at Material Design. MARY XIA: Today we'll show you how building an app with Flutter and Material is expressive, enhanced, and a delightful developer experience. WILL LARCHE: And we'll do it for both Android and iOS, but build it once using Flutter. MARY XIA: Flutter is a way to build native mobile apps. You can build apps that are expressive and flexible, create high-quality experiences, and iterate quickly. You can use Flutter today. It's already being used by developers and organizations around the world. Flutter comes pre-built with a large library of widgets, such as containers, list views that are efficient, scrolling, gestures, and more. WILL LARCHE: Now, Material Design is an adaptable design system, backed by open source code, that helps designers and developers make beautiful, usable products faster. It's a visual design system used in millions of apps and sites all around the world. What's new this year is Material theming. Material theming helps you systematically apply brand throughout your designs. As you can see, Material is more flexible than ever. The shape, color, typography, the animation curves, are all customizable to match your brand. You could even choose color palettes from our online color generator that are generated for you, and typography themes. You can even change the shapes in your app to have a theme of their own. MARY XIA: Will, I love how this is taking shape. WILL LARCHE: Right, yeah. And I'm excited to announce today that Flutter is a first-class platform in Material Design. [APPLAUSE] From today forward, you'll find documentation for Android, iOS, web, and Flutter, throughout Material Components, the Material Tools Suite, and the Material Guidelines. MARY XIA: So it sounds like Material and Flutter have really embraced each other. What's it like building an app with them? WILL LARCHE: I'm glad you asked, Mary. Let's see how they work together. And a reminder, you can do everything that we're about to do at home, today. Behold Shrine, our retail app. I love the clothes, I love the home goods, but unfortunately, the UI is disturbingly last season. MARY XIA: Who else has seen an app like this? WILL LARCHE: Yes, I think we all have, Mary. WILL LARCHE: Yep, Google Docs. They look very similar. When Material first came out, many apps faithfully followed the Material guidelines. And so they ended up with apps that looked identical to each other. Or worse, they looked like Google's brand, rather than their own. We want your apps to look like your brand. WILL LARCHE: Material theming helps with that. It applies consistent brand elements throughout your UI. MARY XIA: So let's apply Material theming to Shrine and show how Material on Flutter is expressive, with its customizable widgets, layouts, and themes. WILL LARCHE: Enhanced, with new components and styles like our text fields and backdrop. MARY XIA: And delightful, offering developer tools and easy extensibility of components. WILL LARCHE: Now, what is a widget? In Flutter, a widget is pretty much everything. There are your buttons, your cards, your text fields, all your views are widgets. You can also compose your own widgets from existing ones. And we'll show you how to do some of that today, too. Material Components is a library of widgets that are expressive, enhanced, and delightful to work with. MARY XIA: So we'll start by building this app. We've already built it. We're going to enhance it now. It is built with the default theming and doesn't have any of the latest of material. WILL LARCHE: So let's look at the guidance our designer gave us. It's a font, logo, shape, layout and color. MARY XIA: OK, great, let's start with the color theme. WILL LARCHE: Mary, will you code? MARY XIA: Yes. WILL LARCHE: Thank you. I will stand here and talk, because I crave attention. So we've already used a lot of Material Components to build the unthemed app. So we've imported the Material Flutter package in all of our apps files. We have the unthemed app running in the Emulator. Here's Shrine's login page. And here's its homepage. Both of those pages are routed to the screen by the Shrine app widget. This is what gets passed into the main function, which is run when we start our app. It's the highest level widget in our project. It returns a Material app widget in its build function. Let's take a look at that Material app widget. Its home property is set to a homepage widget, which we've built just for Shrine. There's also a theme property. And you can pass in a themed data in the app's constructor. All the descendants-- widgets- of the app will have this theme applied to them. Let's look at the color theme our designer gave us. The color theme has most of the colors you need in an app, like primary and secondary colors, background, and a surface color for things like modals. It also has the colors you need for text and icons that are drawn on the primary, secondary, background, and surface colors. There is even a primary variant for any time the primary color is against another color and that combination is inaccessible. We've already copied the Shrine color values into a color constants file for convenience. You can see little swatches of the colors on the left side next to the line number. By the way, Material icons will also appear in this way. The Material package already has predefined colors, like colors.red. But Shrines designer is using custom branded colors, like millennial pink and brown. Mary started a theme already. She's going to add those colors to it. These are the colors our app will use on a global level. She started with a light theme and now she's changing some of the values. She's adding a primary text theme from a function that she built herself. It's going to use as a base the existing primary text theme. And then it's going to change one of the values to be brown. Now she's adding an icon theme. She's going to again start with the base theme, and then change the values that she wants to be different. Copy with, by the way, is a very common method that you'll see on a lot of Flutter widgets. It allows you to copy an instance, but change whatever parameters you put inside. Now she's going to set the button color throughout the app, for raised or contained buttons. Reload. MARY XIA: What do you think? WILL LARCHE: It's better, no more blue. Thank you, Mary. So let's work on the font on those titles, please. She's going to set a custom font for large type, like titles and headlines. I always thought the font family sounded so wholesome. It's a slight change, but at least it matches our logo now. It's not default Roboto for larger type. Now to the login screen. So the login screen itself is a widget. And every widget has a build method. In it, you construct your UI. Our build function has a safe area widget, which can account for the notched top on a lot of newer phones. Inside we have the logo, the text fields, and buttons in a list view. We could have used a column widget, but the list view automatically handles scrolling on smaller screens and when the keyboard appears. These are all widgets provided by Flutter. Note that the build text field function Mary and I wrote returns a widget. This is directly called in our build function. We can even pass in our own parameters to this function. It's not a static layout. Right now, the text field is automatically using the global color theme's primary color as its active color. And you can see when she's typing, the floating placeholder and underline decoration are not very accessible. We could change our global theme's primary color, or we could change just the primary color of our text field to the primary variant. Each widget can override their ancestor's theme by being wrapped in a new theme. If we highlight a widget and press Alt-Enter a shortcut menu appears. And one of the common shortcuts is wrapping a widget with another widget. We'll wrap the text fields in that copy of the theme that has the primary variant as its primary color. Now you can see what you're doing. Our material theme also has a shape story that's angled, based on our logo. Mary's setting the shape of the Next button to the beveled rectangle border widget. This is a component that Flutter provides out of the box. It takes the size you want the cuts to be and returns an octagonal outline. As you can see, the button is now eight-sided. By the way, if you're working without a designer, or you're a designer yourself, we now have a tool that can help you generate palettes of colors for theming. Imagine we didn't have a complete brand guideline, but we had a color that we were already using consistently, or wanted to use more consistently. You can go to this website material.io/design, and it can suggest complimentary palettes and extended tonal palettes to go with that color. So just for fun, let's see how Shrine would look if it were built from charcoal. We added some colors earlier in our color constants file. Mary's changing to an alternate theme function that uses those colors. See, very different alternative theme very easily. Now, let's go back to the real theme. So we've seen how color and shape can express your brand, but what about layout? Well, our designer has read the new guidelines on image listing cards, and decided to make an asymmetric layout part of our Material theme. At the moment, our products are displayed in a simple grid of cards with images. And this is the default for grid view. Our designer wants it broken up into threes, with asymmetric alignments, and aspect ratios inspired by the angles in our logo. It's a custom design just for our app. We're going to use a completely custom widget called asymmetric view widget for asymmetric layout that we made earlier. It's based on the list view widget in Material Components. By the way, you can find the source code for everything we're doing today in the Material Flutter code labs. Mary removed the grid view widget we had inserted our asymmetric view widget. Since the asymmetric view is built on top of a Flutter list view widget, the widgets are recycled as we scroll. Flutter list views let you specify the scroll direction, and we've set it to horizontal. The asymmetric layout code is less than 100 lines. It's a very expensive-looking component that's-- oh-- MARY XIA: What? What's going on? WILL LARCHE: I have that scarf. [APPLAUSE] MARY XIA: Will, you have every scarf. WILL LARCHE: Yes, thank you, Mary. Anyway, so Flutter lets you develop in one code base, but deploy it at both Android and iOS. The app is looking great. And I want to see how it looks on iOS, so let's switch places. MARY XIA: Sounds good. WILL LARCHE: We'll be using the iOS simulator for the rest of our development to show how easy it is to switch between the two platforms. You just set the device selector to iPhone simulator. MARY XIA: OK, great. So Will has just shown us how you can express your brand in your app. Now I'll talk about how the enhancements to Material can help make your apps stand out, and make it easy for you to use existing components, and use guidance to build components that, well, you know, also express your brand. The first thing Will's going to add is an outline input border to the text field. Right now, our text fields just have a line on the bottom saying it's a text field. The outline input border wraps the whole text field with a border, making it obvious that it's something that users can fill in. Now, you might be wondering, how do we have any proof that this is a better design system, or that Material Design is a great design system? Well, we did a lot of research. And it turns out that these types of text fields are much more performant, and users are more likely to see them in a busy form. They know that it's a call to action. So that's why we're using it here. You can also watch the talk "Measuring Material" to learn more about Material research. You know, that looks great, but it doesn't look as edgy as the Shrine brand really is. You don't cut corners with Material Design, unless you're using a cut corners border. This border literally cuts the corners off of your text field's outline so that it can match the button and it can match our Shrine logo. There, it looks octagonal. Looks great. Will, we can see your password. WILL LARCHE: Oh, you shouldn't be able to know that my password is yaasresearch. MARY XIA: Yeah, so the text yields come with a built-in property obscure text. And now we're passing in our own Boolean is password so that we can hide our password. As I said, we build our text fields using our own function, and it returns a widget. And we just pass that right into our build function. Great. Now that we've spruced up our login page, let's see what we can do on our homepage. Our homepage currently is one page with a menu bar. What we want to do is add a backdrop. A backdrop allows you to have two layers in your app. It's an intuitive way to display both a menu and some content, rather than having a menu pop in from the side. Will's is going to remove the app bar from our current version, because the backdrop comes with an app bar. Will and I built the backdrop ourselves, but it came entirely from Guidance by Material Design. They have a lot of specifications for how you can do layouts and what sort of navigation can exist. After he's done that, he's also going to remove the homepage from our home property in our Material app and replace that with the backdrop. Now, the backdrop is essentially just a stack. A stack is a way of layering various components on top of each other-- for example, a footer. Here, our backdrop has a front panel and a back panel, and they're stacked on top of each other. The front panel is our homepage, and our back panel will be a menu page. So let's see how that looks. It has the Shrine edge. We added that as well. Let's try clicking on the icon and seeing whether or not it goes up and down. No, because we have not implemented that yet. OK, so let's do that now. And to do this, we need to use a transition or animation. We're going to use a positioned transition. Essentially, this is just a way for the parent to tell the child, hey, you're my child widget. You start off at this size and location, and you'll end up at this size and location. For this case, we want to animate from closed, which is the bottom, to open, which is with the whole home screen open. So let's start with a panel animation. Now this animation is of a type relative rect. So this is the way you tell your animation that it wants to start off with a certain location and size, and where it should end. It takes in a begin and an end and a controller. So Will's typing that out now. We've already predefined what the panel height and the height of the app bar should be. And also, we need to pass in a controller. The controller is responsible for orchestrating the actual animation. Every frame that is drawn is determined by it. We now pass the panel animation into position transition widget. Flutter comes with a lot of different transitions-- for example, fading, rotation, scaling, and much more. They come out of the box, so all you have to do is use them. It takes in a rectangle property, which is our animation, and it takes in the child, which is the child we want to animate up and down. So let's try animating. There we go. [APPLAUSE] Now, back to the animation controller. As I said earlier, it's responsible for drawing the new frames. Well, let's take a look at it. This comes out of the box with Flutter. And this is the code that is used. It's open source. You can see that it animates from the value 0 and 1. You know how I said that Flutter comes with a lot of animations already? Well, you can also build your own if there is something really custom you want. And then you map your widgets to these values 0 and 1 while they animate. OK, so the material guidelines also suggest that for a backdrop, that users would like to tap on the top. You've switched to the Android phone. WILL LARCHE: I know, I hit the wrong button, I'm sorry. It's live. It's loading the new-- it's loading the iPhone simulator. MARY XIA: Just tab out to the uh, oh, OK. There we go, back to the backdrop version. Anyway, so that Material guidelines say that you want to tap on the top of your backdrop in order to animate up and down, as well as tapping on the app bar itself. Currently, tapping on the top doesn't do anything. We now add a gesture detector. Flutter also comes with a lot of gesture detectors, like on tap, on drag, on long press, a lot more. They're meant to be extensible. They take in a function. Functions are first class objects in Dart. And this means that we can pass in any function and have your tap and gesture do anything you want-- show hide, change a variable, other things like that. So Will is now setting that up and putting a parens after the 2. There we go. Now when you tap on the backdrop, it should animate. WILL LARCHE: Oh Mary, I did it wrong. Classic Will. MARY XIA: That's OK. WILL LARCHE: Help me debug. MARY XIA: Oh, that's OK. Well-- WILL LARCHE: Oh. There we go. MARY XIA: All right, cool, we're all set. [APPLAUSE] Great, well, now you've seen how all the enhanced new things for Material have helped us build an app that is much more enhanced, and well, kind of cool and much more unique. Now we're going to talk about how delightful the developer experience is. Sometimes someone gives you code, and you want to make changes to that code. For example, right now our image and our text are very close together. We want to put some space between the two. So you can look at the image and admire the goods, and then look down and see the price tag. How do we do that? Well, we can use the Flutter inspector. The inspector maps between the UI and the exact line of code where that widget was being created. Now Will's going to demo the inspector. You just tap on the inspect button. And if you tap on anywhere on your app, it will pop up a box. And this box will then take you to the exact widget for that app. Currently we are tapping on that, and it shows that-- Will, I think your inspector's running for-- WILL LARCHE: Doesn't want to show the widgets, but we've got the render tree. MARY XIA: OK, the render tree is a much more detailed version of your widget tree. It shows literally every single thing that is being drawn, whereas your widget tree only shows the widgets that you've drawn, and not only your widgets, but also widgets that are being drawn by part of the system. Your widgets are drawn in bold color. And if you right-click, you can jump to this exact line of code. Well, here, we'll know that this actually points to the product card, which is responsible for drawing the actual card with the image and text. So let's check out our product card widget. Remember, this was given to us and we didn't build it. Although technically, we did build it. All right. Inside the product card, there are two functions-- build image and build text. They are arranged in a column. We want to put space between the two. We look at our column and note that it says cross axle alignment at center. There's no main axis alignment. Through reading the Dart docs, or through reading, trying stuff out, usually even checking in the inspector, which shows all the properties that are being defined, you'll find that our main access alignment is set to start, even though we never actually set it. What does main access alignment mean? WILL LARCHE: Main axis alignment is the direction you want things to begin in the scroll direction. So it starts at the top. MARY XIA: So it seems like our image and text are all going to start at the top. Let's try changing that to center, so that inside the space allotted to our product card, maybe our text will center itself, rather than align itself to the beginning. There, there's a little bit of space, but that's not enough. Let's change that to end. We want more space. There, that looks much better. WILL LARCHE: That looks good. MARY XIA: Now you can see your image and text with some space in between. Well, while we're here, let's also change our image aspect ratio. Currently the images have an image aspect ratio, I want it to be one. I want my images to be square. OK, that looks great. But who here has had a cat walk across their keyboard? There's more than that, I'm sure. All right, well, cats are the number one cause of typos in code. It's a proven fact. WILL LARCHE: It's true. I've actually never made a mistake in code. Even today, it was a cat. MARY XIA: OK, so let's say a cat-- Nate, what's your cat's name? WILL LARCHE: Nate. MARY XIA: Oh, whoops. All right. Wait, wait, why Nate? WILL LARCHE: He's my concat Nate. MARY XIA: OK. All right, that's a classic, right? WILL LARCHE: You loved it. MARY XIA: OK, well, let's say, Nate the cat negated the aspect ratio. And so now it's negative 1. What happens? You know your app's going to crash, right, because negative 1-- and it's still-- the compiler accepts it because it's still a float. But no, only the part that-- the widget that like has a negative 1, the aspect ratio widget crashes. Everything else still works. Your app still scrolls. You can still go to the menu. So now let's just change that back and reload, and let's see what happens. There, all right, all fixed. So this is one of the cool things about Flutter. We've been making changes, and they've been loading really quickly. Only the widgets that are being changed are being redrawn. We've been restarting the app in this demo. But earlier you saw the colors would show up immediately. Asymmetric layout showed up immediately. We did not have to restart the app. So you could easily backtrack and rebuild UI and try things out. And if it doesn't work out, that's OK. You don't waste that much time. Also navigational state is being preserved during hot reload. A couple of other cool things-- we've been autoformatting our code as we've been building. And also, you can add closing labels to your code. These closing labels tell you what widget has just finished. Let's see what it looks like. There, see? Now you know you have a text. You have widgets and columns. This way you can tell where those braces mean. Great. Well, Will, I think that looks pretty good. What do you think? I think it looks lovely. WILL LARCHE: Yeah, I don't think it looks anything like the generic blue app we had when we started. MARY XIA: All right, well, let's come back here. All right. So let's recap. We just revamped an outdated app with Material Design and Flutter. WILL LARCHE: Material theming and the asymmetric layout showed how expressive our app can be. MARY XIA: The new text fields and backdrop showed the enhancements to Material Components that you can use today in Flutter. WILL LARCHE: And all the Flutter tooling made a delightful experience for us developers. MARY XIA: You're used to seeing people give you custom complicated designs. And you want to work on them, but they're just going to take too much time. But with Material Components, your designs and code live in the same world. MARY XIA: With Flutter's support for Material theming, it's no big deal if your designers suddenly says, "Let's change everything that's light blue to dark blue." You might not have to say no to your designer anymore. We want you to spend less time on boilerplate and more time building the things that make your app special. MARY XIA: So you should import the Flutter Material package today. Also, be sure to check out our code labs where you can code everything we talked about in this talk. They're available online and in the code lab at IO. WILL LARCHE: Also check out the Total Mobile Dev Made Fun with Firebase and Flutter at 2:30, and Build Reactive Mobile Apps with Flutter. MARY XIA: We're going to be here after for questions, and in the Sandbox from 2:30 to 6:00 today. [APPLAUSE] WILL LARCHE: Everything else you need is on flutter.io and material.io. MARY XIA: Now, go code beautiful UI with Flutter and Material. MARY XIA: Thank you! [APPLAUSE] [PEPPY MUSIC]