Afrikaans
Akan
Albanian
Amharic
Arabic
Armenian
Azerbaijani
Basque
Belarusian
Bemba
Bengali
Bihari
Bosnian
Breton
Bulgarian
Cambodian
Catalan
Cebuano
Cherokee
Chichewa
Chinese (Simplified)
Chinese (Traditional)
Corsican
Croatian
Czech
Danish
Dutch
English
Esperanto
Estonian
Ewe
Faroese
Filipino
Finnish
Frisian
Ga
Galician
Georgian
German
Greek
Guarani
Gujarati
Haitian Creole
Hausa
Hawaiian
Hebrew
Hindi
Hmong
Hungarian
Icelandic
Igbo
Indonesian
Interlingua
Irish
Italian
Japanese
Javanese
Kannada
Kazakh
Kinyarwanda
Kirundi
Kongo
Korean
Krio (Sierra Leone)
Kurdish
Kurdish (Soranî)
Kyrgyz
Laothian
Latin
Latvian
Lingala
Lithuanian
Lozi
Luganda
Luo
Luxembourgish
Macedonian
Malagasy
Malay
Malayalam
Maltese
Maori
Marathi
Mauritian Creole
Moldavian
Mongolian
Myanmar (Burmese)
Montenegrin
Nepali
Nigerian Pidgin
Northern Sotho
Norwegian
Norwegian (Nynorsk)
Occitan
Oriya
Oromo
Pashto
Persian
Polish
Portuguese (Brazil)
Portuguese (Portugal)
Punjabi
Quechua
Romanian
Romansh
Runyakitara
Russian
Samoan
Scots Gaelic
Serbian
Serbo-Croatian
Sesotho
Setswana
Seychellois Creole
Shona
Sindhi
Sinhalese
Slovak
Slovenian
Somali
Spanish
Spanish (Latin American)
Sundanese
Swahili
Swedish
Tajik
Tamil
Tatar
Telugu
Thai
Tigrinya
Tonga
Tshiluba
Tumbuka
Turkish
Turkmen
Twi
Uighur
Ukrainian
Urdu
Uzbek
Vietnamese
Welsh
Wolof
Xhosa
Yiddish
Yoruba
Zulu
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.