[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]