MARTIN AGUINIS: Hi, everyone. I'm Martin from
the Flutter team. Today, I'm going to show you
how Flutter's widget composition can help you quickly build
out a beautiful interface for your applications. If you haven't
tried Flutter yet, it's Google's new
mobile UI SDK that can help you quickly build
native iOS and Android apps from a single codebase. Widgets are the building block
of any app built with Flutter, and their functionality
spans from providing a framework for your entire
app, like the scaffold widget, to accepting input,
like text field does, or even animating an ink splash. Every widget has its
own particular purpose. And you, the developer, build
your app through composition, putting individual
widgets together until they add up to
a great interface. Let me give you an example. Say you're an engineer
at a shop that builds mobile apps
for other companies. And one day, your biggest client
comes to the office and says, we have to talk about an action
button on our shopping app. The look just isn't working. We need something that
really feels like our brand. As a Flutter developer,
you can say, no problem. Have a seat and I'll
pull up the code. All right. So here's your client's app. And if we zoom in, you
can see this default looking floating action button. There's nothing wrong
with the basics, but you can see why
the client might want something a little more custom. And here's the code that
produces the UI you just saw. It's written in the Dart
programming language, which is what Flutter uses. There is the MyHomePage
class up at the top. And here's the bit
we're interested in, the floating action button. Let's create a new file
and define a new widget to use instead of the default.
We'll call it FancyButton. There we go. Let's import a couple of
the basic Flutter packages. There is the foundation and
the material package that's got a ton of widgets in it. And I'll define
FancyButton as an extension of stateless widget. I'm going to skip
over the details of stateless widget for now. The important thing, as
far as we're concerned, is that stateless widgets
don't have mutable properties or a state that can change. You just construct one
and it's good to go. Speaking of properties,
let's give the button a callback for
when it's pressed. And we'll need a constructor
to inject the callback. So let me add that. If you're new to
Dart, you may not have seen this in a
constructor before. It just means that
the constructor should have a parameter
that matches the property and handles the
assignment for you. I can also put braces
around the parameter to make it an optional
named parameter. You'll see how this works
when this gets invoked. And use the required
annotation to make sure it's always passed in. And there's one method I need to
implement here, which is build. This is call by Flutter,
and it's basically a way of asking your widget,
hey, who are your children? What widgets are below
you in the hierarchy? I've just got a
placeholder null in here so that I can go
back to my home page. Let's get the new file
imported, and then I'll come down here and replace the
default button with my widget. You can see the name
parameter for onPressed. I'll give it the same
method that the other button was firing. OK. Let's get back to FancyButton
and the build method. This is where the
composition happens. I'm going to start putting
child widgets together to define how this widget
looks and performs. Let's start with some text. Maybe the client wants the
button to say PURCHASE. Now I'm going to build this. And since this is
the first build, it's going to take
a few seconds. Once the app is
up and running, we can use hot reload to
cut the refresh time to less than a second. But more on that later. In the meantime,
there's the interface. And there's the word
PURCHASE in the corner. So we've got something going. OK. So we need this widget
to do more than just print black text. And in Flutter, you
can add a capability by putting widgets together. So let's wrap the text
with a basic button called raw material button. The text widget now
becomes its child, and I'll add a
comment at the end here so that the auto formatter
makes it look nice and pretty. Raw material button
has a few properties. So let's start with color. I'll fill it with deep
orange and use regular orange for the ink splash. Now, let's save and
do a hot reload. That's going to
update the app's code without restarting the app. And there is my updated button
in about 400 milliseconds. Now, I'm tapping
on the button here. And as you can see,
there's no splash, which is because we haven't
given this raw material button anything to do. So let's give it the fancy
buttons onPressed call back and a hot reload later. I get a nice splash. What's next? Say the client wants
a rounded button. I can do that by giving mine
a stadium border as its shape. And I can call that constructor
with a const keyword here. That's always nice. In fact, it reminds me,
I don't need the new on raw material button. The new keyword is
optional in Dart 2, so I can pop it right out. OK. Let's hot reload and
see the new shape. Boom, rounded edges. This quick cycle
of making a change, see the result,
making the change, see the result is something
Flutter was designed, from the start, to provide. All right. What else can we do? Let's give the text
a little more pop by changing it to white. There is a style
property for text widgets that can help me with that. We can give it a textile object
with the color set to white. OK. I've got some white text. What about more padding? Sounds like a fun job
for the padding widget. I'll wrap the text in an
instance of padding and I'll make it symmetrical, 8 for
vertical and 20 for horizontal, and hot reload. There's the padding. What else might the client want? How about an icon? A lot of buttons have icons. The problem here is that
padding takes a single child. But we want it to have two-- text and an icon-- so we need a container. Flutter has a number
of them and they are, as you probably
guessed, also widgets. We can use a row widget to
display the icon and text widgets next to each
other horizontally. Instead of a child property, row
has a property called children, which takes a list of widgets. Let me finish up by
getting the icon in there. All right. And now to hot reload again. And whoa, that's not right. Looks like I forgot to set the
main axis size for the row. The main axis for
row is horizontal. So this code tells
the row widget to use the smallest
amount of space it can. All right. Let's hot reload again. There we go. This is another nice
thing about hot reload. I just messed up the UI by
forgetting to set a property and I was still able
to go back, add a fix, and keep going
without a restart. Next, how about a little space
between the icon and text? There is a great widget
for that called SizeBox. You can give it a
dimension or two and it will take up some space. And you know what? All three children of
the row are constants. So let's just move that
const up to the list itself. There we go. All right. Hot reload. And there's SizeBox at work. Not bad. At this point, we've composed
a completely new button with six widgets,
each of them handling its own particular
responsibilities and combining to give the
client a button that's vibrant and unique. So far, we've
mostly used widgets to control basic
presentation details. But they can do a lot more. For example, say you're
displaying an image and you'd like to know
when the user taps on it. Just wrap the image in a
GestureDetector widget. There are properties for taps,
long presses, drags, and more. Just like the graphics-focused
widgets you've seen, GestureDetector handles
it's one particular area of responsibility and that's it. All right. Let's get back to the app and
put some more widgets to work. OK. We're back with a button. Let's say the client's
so impressed with what you've done that they really
want to push the envelope. How about a vertical
floating action button? No problem. There is a widget for
rotating other widgets. It's called RotatedBox and
we can give it 3/4 turns and get this. It's vertical and everything. But maybe just because
you can do a thing doesn't mean you should. So let's pack it out
with the Remove widget. You can use RotatedBox on
a lot of stuff, though. Say the client preferred
the little compass icon to point the other way. No problem. There it is, leaning
back instead of forward. By the way, so far
I've been composing with widgets that are
part of core Flutter, but it works the same with
widgets built from scratch. For example, let me drop
some code in here real quick. Say I had another widget
that I'd already built called PulseAnimator, with
a child property of its own, and its job was to apply a
pulsing animation to the child. You can use the same
composition strategy with it that you do with
the stock widgets. Here, I'll add it to the
hierarchy and make this text its child. And when I hot reload,
there is the animation. So there you go. That's eight widgets
in combination to make a great button
and a happy client. So now we've got an updated app
and a happy client, all thanks to widget composition. That's it for today. But if you'd like to
learn more about Flutter, we've got links to
guides, sample apps, and a bunch of other resources
in the video description below. So check those out
and head to Flutter.io to get started today.