All language subtitles for 12. Composition vs. Inheritance - Building Flutter Widgets From Scratch

af Afrikaans
ak Akan
sq Albanian
am Amharic
ar Arabic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French Download
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranî)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
fa Persian
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

0 Now so far we've seen that we can customize our widgets by doing a number of things. We can either set 1

the properties of each of our widgets, 2

so if our car widget had a color of black, we could simply set its color property to blue. 3

And because our widgets are immutable the old one gets destroyed and a new one gets created with the 4

updated properties. 5

Now we can also change its style or any of the other properties that is predefined by Flutter. 6

So for the slider widget, we can change its activeColor, 7

we can change its divisions etc. But there's only a limited number of these properties that we can change 8

because these rely on preplanning from the Flutter team to create properties for us to change that are 9

commonly needed. 10

So if we wanted to dig deeper when we wanted even more control, 11

then we went into the SliderThemeData where we were able to set the theme for more specific things 12

such as the disabledActiveTickMarkColor or whatever it may be. 13

But then we also get to a dead end right? 14

What if we wanted more customization and we wanted to create a custom widget from scratch? Well in a 15

lot of programming languages if you come from Swift or Java or you've done some development for iOS 16

or Android, then generally the way that we go about this is through inheritance. 17

So we would inherit a component such as the slider, and then we would override some of the properties 18

or methods of those components. 19

And this is generally how we do things in both Android and iOS. But in Flutter, the way that it's built 20

favors composition over inheritance. 21

So what does that mean? 22

It means that we want to try and build things from scratch from the simplest widgets possible and that 23

way Flutter can keep our component's performance and keep our apps fast. So how do we actually go about 24

composing widgets? 25

Well even if we think about a basic widget such as a container, it's actually composed of smaller widgets 26

such as a LimitedBox with a ConstrainedBox with some Align with some Padding with a DecoratedBox. So 27

a whole bunch of widgets that are very basic and do very simple things came together to build a container. 28

And this goes back to that idea of having very simple immutable building blocks that are like small 29

pieces of Lego. 30

And by combining these simple widgets together, we can build a more complex and more interesting widget. 31

So rather than taking a pre-built large widget such as a FloatingActionButton and trying to somehow 32

inherit it and then override certain things about it, it's actually much easier in Flutter to just break 33

it into smaller pieces to see how it's created by looking at the open source code and then just building 34

it together yourself using the simplest, the most basic building blocks that Flutter gives you access 35

to. And that's exactly what we're going to do in this lesson. All right. 36

So we've already done the icon cards, the slide card. 37

Now all we have is this final row to create. 38

So let's go ahead and do that right here. 39

So we currently have two reusable cards and we're going to have to give them some children. 40

So let's add a carChild to the first one. 41

And in this case because we have to stack a number of things on top of each other from the top to the 42

bottom, it also makes sense to add in a column. And in our column, we're going to already set our main 43

AxisAlignment to center. 44

So this way everything gets bundled into the center of the column along the main axis which is the vertical. 45

And then we're going to give our column some children. 46

So the first one is going to be a text widget which simply is going to say 'WEIGHT'. 47

And in this case we're going to use the same style that we've been using so far, which is the klabelTextStyle 48

constant. 49

And now we should be able to see our text show up on screen right in the middle of our column. 50

So the next thing is to add the actual numbers for the weight that the user is going to input. 51

So again we're going to need a variable that's going to keep track of this. 52

So we're going to add it just below height and I'm going to keep it as a whole number as well. 53

And our weight is going to start out being let's say 60 kilos 54

maybe, that should be all right. 55

So we've got our weight number as a variable up there. 56

So we can now add a another text widget just as we have done for our height. 57

We're going to add it in here as the data. 58

So we'll put in the weight 59

and we're going to change it to a string because that's what the text widget wants. 60

So that's what it's going to get. 61

Now our weight is also going to be styled. 62

But this one is going to be styled using the numberTextStyle which is that super large bold looking thing 63

that looks very similar to this. 64

So now we have our weight and we have our starting weight. 65

So all we need to do now is to add some buttons so that the user can actually toggle the weight and 66

their age. 67

So these buttons, we've seen from previously when we used our FloatingActionButtons, look very similar 68

to this right? A round button with an icon child in the middle. 69

So if I go ahead and add in a FloatingActionButton here, 70

so I'm just going to use FAB for short so that trusty Android Studio pulls up the thing I need. 71

And now if I go ahead and hit ENTER and save, then you can see that my FloatingActionButton pops up 72

and it looks really similar. 73

All I would need to do is probably give it a child. And the child is probably going to be an icon and 74

the data for the icon 75

we could probably just use one of the icons and let's just use add. 76

So now you can see we have a round button with an icon in the middle, and it styled in this color because 77

we're kind of using the dark theme but it's pretty easy to change up the color as well by changing the 78

backgroundColor. So we can change it to a nice sort of light gray maybe color and or do 0xFF so fully 79

opaque, 4C4F5E. 80

So this is what we've got so far. 81

So let's change that icon into a white color. 82

So we're going to go into the icon widget and change its color to colors.white for convenience sake 83

and now this is what we have. Now we want two of those 84

so we'll need a row. 85

So I'm going to wrap my FloatingActionButton inside a row widget and we're going to add one more. 86

And I'm going to paste it right below here and maybe we'll add a sizedBox as well so to give it a little 87

bit of space in between. We'll give it a width of maybe 10. 88

Let's try that and see what that looks like. 89

All right. 90

That looks pretty neat. 91

All we would need to do is change my row to be centered along the main axis 92

and now we should have it right in the middle. 93

All right. 94

So it looks good. 95

But the problem is that if we actually read the FloatingActionButton documentations, you can see that 96

it says pretty clearly that use at most a single floating action button per screen. 97

And they have a specific use case. 98

Now it's not just that the documentation recommends against it, but also what if we wanted something 99

that looked different? 100

What if we wanted a custom shape for our floating action button or we wanted it to look exactly the 101

way that we want it to? 102

So so far we've been using pretty much Flutter components out of the box, and we've either tried to combine 103

them together in different ways so that we create our own widgets out of a combination of Flutter widgets, 104

or we've been digging deep into the themes of the widgets that we've been using from material and updating 105

specific parts of it to make it more like the design that we have in mind. 106

But in this lesson I want to show you how you can actually dig into the code for each of these widgets 107

because remember Flutter is completely open source, so all of the components you're looking at the floating 108

action button or the sliders, you can see all of the source code and you can't do that with something 109

like say iOS. You can't actually see how an iOS button is created. 110

The benefit of being able to look at the source code is that if we hold down CONTROL or COMMAND and 111

click on our floating action button, we get taken to our floating_action_button.dart file. 112

And in this file is all the code that's required to create a floating action button. 113

So if we search for its main build method, we can see how this thing is built. 114

So here we go. Here's our build method for our floating action button and it copies over the theme data 115

from the main app theme and it sets the foreground color or an accent theme and then we go about creating 116

the actual button. And you can see that the floating action button is created from a basic component 117

from Flutter called a RawMaterialButton. And this has a number of properties such as what should it do 118

when it's pressed or its elevation etc. and we can dig even deeper. 119

So if we hold down CONTROL or COMMAND, we go to the raw material button and we check out its own build method 120

to see how this thing is built. 121

Then you can see that it's built using a constrainEDbox which has an InkWell which can detect taps. 122

Now this is here because the raw material button is a button right? So it needs to detect touches. 123

But if we didn't need that at all then we could simply just create a material. And if we CONTROL + click 124

further on material then we go to the main material.dart page and if we have a look at its build 125

method, then you can see that this is also built from a number of smaller components. 126

Depending on how deep we want to go down the rabbit hole, we can actually create as custom a design or 127

a component as we need and we don't have to rely on the default Flutter component at all. 128

And you can see that when you go into the packages for Flutter, you can see that there's a lot of packages 129

that people have created when they've built their own custom things such as a custom slider. 130

So for example if we have a look at this slider, you can see this person has built a two thumb range 131

slider which is kind of neat. And you can see that they even tell you how they built this widget. 132

They've basically created it as a pure drawing from scratch in order to display this custom widget. 133

So what I'm trying to say is that the widgets that Flutter provide are super convenient and in most 134

cases they're all that you're going to need. 135

But sometimes if you have a design that you want to implement in particular, then you don't have to be 136

limited to the shapes or the colors or the styles of the default widgets and you can simply just build 137

your own. 138

So let's go about building our own raw material button. And we can create it inside our rows to act as 139

our buttons instead of having to rely on floating action buttons. So right at the bottom I'm gonna create 140

a new stateless widget using my shortcut stless. And I'm going to call my widget a RoundIconButton. 141

So I'm gonna try and be as descriptive as I possibly can. 142

Now my round icon button is going to be built very similar to how the floating action button is built. 143

It's also going to depend on a raw material button. 144

So let's return a RawMaterialButton. 145

And in this case we have a number of properties that we can tap into including things such as the fill 146

Color or the highlightColor or the splashColor or the elevation, but you can see that they all come 147

with default 148

so we only need to set the ones that we actually want to change. So let's go ahead and set some properties 149

for our raw material button. 150

Well firstly it's probably going to need a shape. And you can see that the shape property expects something 151

that is a ShapeBorder and by default it's given a RoundedRectangleBorder. 152

Now that might not be what we want, 153

so let's see what other shapes there are. 154

So when we look at the documentation it tells us that this is the base class for shape outlines and 155

it handles how to add multiple borders together and we can define various shapes. 156

For example we could use circleCorder if we wanted a circle or RoundRectangleBorder for a round rectangle 157

and there's all of these different styles of borders 158

we can choose from. 159

So in our case I'm simply going to choose just a circle border to keep it as a circle and then I'm going 160

to add a fill color to my raw material button and I'm simply just going to copy over the color that 161

I have from before. 162

And now we can simply go over to where we've been using our floating action buttons and we can instead 163

use our custom round icon button instead. 164

So let's check out what it looks like. 165

So it's a little bit smaller than the floating action button and it doesn't seem to have any sort of 166

elevation. 167

It doesn't have any shadows around it. 168

It's just completely flat at the moment. 169

So let's change it and repaint it to the way that we want it to look. 170

Let's maybe update its size. 171

Well how do we know how to do that? 172

Well we can either read through all of the documentation and see which property it is that we need to 173

change. Or even easier, 174

we can take a look at the floating action button and see how the Flutter team actually built this button 175

using the raw material 176

button. We can see that it's got these size constraints. 177

And if we go ahead and try to find this in this file then we can see that it's over here and it's got 178

some constants, minimum size constraints and normal size constraints. 179

So if we look for what these constants are, then we can find that it's actually set to have a box constraint 180

which is tight for a width of 56 and a height of 56. 181

So why do we go ahead and implement this as a constraint in our material 182

button? 183

So it lets add a constraint and put in our box constraints that we've just very conveniently copied 184

over from the Flutter floating action button. 185

Let's hit save and let's see now that our shape is exactly the same as the FAB shape. So let's go ahead 186

and add some elevation to our raw material button and I'm going to add about six pixels of elevation. 187

But right now if we have a look at our button you can see that it's still completely flat. 188

There's actually no shadows and you can zoom in to confirm but there's actually no elevation that's 189

being added unlike this floating action button we've got on the right here. 190

So why is that? 191

Well it's because when all material button doesn't have an onPressed parameter, so it's not able to 192

respond to touches, 193

it's actually in the disabled state. 194

So there's even a setting for the disabled elevation. 195

So if we add that as a six then you can see we now get our elevation. But better than that, we can actually 196

simply just add a onPressed and define what should happen when somebody presses on our round icon button. 197

And if I hit save here, you can see that my shadow stays exactly the same as the floating action button. 198

Now how did I know to change the constraint and also the fact that the onPressed will change whether 199

if the material button is is disabled or enabled? 200

Well of course it's the documentation. 201

So it mentioned here that to define the button size, you change the constraints. And the elevation is 202

for when the button is enabled but not pressed. So buttons are disabled by default, to enable a ,button set 203

it's onPressed property to a non-null value. 204

So there's really no magic here. 205

Everything comes from reading the docs really carefully. Now, 206

the only other things that our material button needs is a child so that we can put in an icon in there. 207

And the icon is going to be different between the left and right. 208

It's gonna be minus on the left and plus on the right. 209

So our raw material button luckily has a child property which we can set and we're going to pass this 210

in into our round icon button. 211

So we're going to set it as a final property and I'm just going to add it as a widget and it's going 212

to be called child. 213

And when we initialize our round icon button, we're going to have a this.child to be have to pass 214

it in to our child property. And then it's going to go right here and be slotted into our raw material 215

button. 216

Now we could leave this as it is and pass in an icon with some icon data but we could also make this 217

a little bit simpler. Given that we're calling this a round icon button, then in most cases it's probably 218

going to be around and it's probably going to contain an icon. 219

So why don't we make our lives easier and just change the child to a icon widget and then only the icon 220

data needs to be passed in? 221

So let's change our property from widget into IconData and we'll just call it icon so that we can pass 222

it in here and we're going to initialize icon instead of an entire child with the icon widget and all 223

of its family. 224

Now we can go into our round icon button and specify an icon which I'm going to change to a FontAwesome 225

icon and I'm going to use their plus sign because it's a little bit bolder and a little bit easier to 226

see. 227

So this is what we have here. And we can now also copy this over and get rid of our floating action button. 228

And I'm going to change this to minus so that I have a minus on the left and a plus on the right. 229

So it's looking pretty neat. 230

So now we've built our very own version of the floating action button and it currently looks pretty 231

much identical to the floating action button. But of course we can customize it to no end because we're 232

using such a basic fundamental building block that we can actually change a lot of its components. 233

For example the shape, 234

so if you didn't want to have just a bog standard circle you could change it to maybe a rounded rectangle 235

for example. 236

So we could choose rounded rectangle border and inside we could change its border radius to use a border 237

radius circular. 238

And then we could provide maybe a radius in there. 239

And now if I hit save we get a rounded rectangle as our buttons. 240

Or you could change it to an ellipse or an oval or even a custom shape. And we could also change the 241

elevation. 242

We could make it completely flat if we don't like the way that the elevated ones look with the shadows. 243

So don't ever feel like you're limited to these default Flutter widgets. 244

The Flutter world really is your oyster and you can build anything you want onto the screen. So I'm going 245

to change this back to my circle because I quite like it as a circle. And I'm also going to change the 246

elevation actually to zero because I actually prefer it completely flat. 247

It looks a lot better to my eye but again it's up to you. 248

You can change it any way you wish. 249

But it's time to actually give our rounded icon button a little bit of functionality. 250

We need to be of to pass in something to the onPressed so that it performs the action of updating the 251

weight. 252

Now we've done this before with the height. 253

So as a challenge I want you to update the weight card here so that when I click on the plus button, 254

it will increase that number. 255

And when I click on the minus button it will decrease the number. 256

So remember set state is your friend. Go ahead and try and complete the challenge. 257

OK. 258

So just as what we've done before with our slider, we need to use set state to update that number here. 259

So we know that the number is currently stored in a variable called weight. 260

And we just have to update it whenever the user clicks on one of these buttons. 261

So inside our round icon button, we need to be able to pass it another property something like onPressed 262

right? 263

But at the moment it obviously doesn't have that property yet. 264

So let's add a final function data type as a onPressed and we're going to add it into our constructor 265

as well. 266

So it'll be this.onPressed. 267

Now it doesn't really matter what you name it. At the moment, 268

I've kept it the same as the name of the raw material button onPressed and I can simply just pass it 269

in here. 270

But the naming is up to you. 271

And I'm going to also mark both the icon and the onPressed as required using my required annotation 272

because our widget's called round icon button so it probably needs to be able to be pressed and it probably 273

needs an icon. 274

So that's my logic for marking these two as required. 275

Now that doesn't really change anything other than the fact that when we create a round icon button, 276

we'll get a warning if we don't have one of those properties added. 277

So for my onPressed on the left which is the first one in the row, I want this to update my weight 278

by decreasing it, because this is the minus symbol. 279

So I'm going to call set state and inside set state I'm going to take my weight property and I'm going 280

to subtract it by 1. 281

And the shorthand for that is --. 282

And in my round icon button that has the plus sign, the onPressed method should increase my weight. 283

So I'm going to call that state and I'm going to increase the weight by adding ++. 284

So it adds it by one every time my round icon button is pressed. 285

So now all we have to do is hit save and check it out. 286

So now if I hit minus, goes down and plus it goes up. 287

So perfect. 288

Now all that's left is to implement the very last card, the age card. 289

So knowing what you know and using what you've learnt, try and complete this as a challenge. 290

And I'll wait for you right here with the solution. 291

All right. 292

So the age card looks pretty much the same as the weight card. 293

So we already know how to create the weight card. 294

And we're going to be reusing this round icon button inside that weight card as well. 295

So right here is our very last card and we're going to give it a card child. 296

And this is going to contain a column. Our column is going to have its main axis centered 297

and it's also going to have some children including a text widget that has the word 'AGE' in it and it's 298

going to have the style that is the constant for the label text style. 299

And then after that text widget, we're going to have another text widget which is going to contain the 300

actual number for the age. 301

So we're going to need to create a variable up at the top. 302

And it's also going to be an integer which is going to start out let's say maybe 20, doesn't really matter, 303

your choice. 304

Now down here we're going to include that age as the text, but of course we have to convert it from an 305

integer to a string. And the style for the age is going to be the KNumberTextStyle which is that large 306

font size. 307

So let's check on our design make sure that everything looks as we expect it to. 308

And now all we need is a row that contains our two buttons. 309

So let's add a row and let's center its content along the main axis, 310

exactly the same way as we did before. And it's going to have two buttons. 311

So we'll add two children and it's going to have our round icon button and the round icon button requires 312

two properties. 313

So those get added in as soon as we hit enter 314

which is kind of neat. 315

And the icon for the left one is going to be FontAwesomeIcons.minus. And once it's pressed what 316

we want to happen is we want to set state and we want to reduce the age by 1. 317

Now let's add a sized box so that we can space out the two buttons from each other. 318

And I'm going to add a width of 10 and then we can simply add another round icon button. And this one 319

the icon is going to be the plus sign, 320

so .plus and when it's pressed, we're going to set state and we're going to add to the age, 321

so age++. Now all we have to do is check to see if we have any errors and we have one here, it's 322

because I forgot a comma. 323

Now if I hit save, Dart is reformatting my code and I can now check out my app. 324

So I've got my weight, my age, my male female height and our entire interface is pretty much complete. 325

So I can click on a card to choose my gender. 326

I can move around the slider to choose my height. 327

So let's put that on my height and then my weight is about, yeah but 63 and my age is a secret. 328

So now we're ready to go ahead and compute our BMI from all the data that is received in this user interface. 329

And in order to do that we need to be able to create a second screen and navigate to it. 330

So this is the first time that we're creating a multi-screen app and we're going to be learning how 331

to do exactly that in the next lesson. 332

So I'll see you there.

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.