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 in the last few lessons we've been refactoring our code and making it simpler, easier to read and 1
more succinct. And in the process we've learned a lot of the fundamentals of Dart that enables us to do 2
this such as enums or const, final parsing function and a whole lot of programming knowledge. 3
But in this lesson we're going to get back to our design and we're going to build out the next card. 4
Now the next card is going to be a slider and we're gonna be using a Flutter slider but we're going 5
to customize it to our liking. And in the process we're going to learn a lot about customizing Flutter 6
widgets. 7
So first things first, let's head over to our next reusable card, which is right here. And at the moment 8
it doesn't really do anything. It's completely empty. 9
So let's give it a cardChild. The cardChild property is going to hold a number of things. Because we 10
have quite a few things that are going to be stacked vertically, 11
it makes sense to create a column widget. And it's going to have a bunch of children, the first of which 12
is going to be a text widget. And our text is simply going to say the word height because this is going 13
to be the height input. And I would really love for that text to have the same style as the male and 14
female text here. 15
So the same font size, the same color and the same font. And at the moment that style is coming from a 16
constant that's defined in our icon_content.dart file. And it doesn't really make sense to reach into 17
the icon content file to be able to define a label that's on my input page. 18
It seems like that would get really messy. 19
So this is a good time to talk about creating a dedicated constants file. As we create our design and 20
our user interface, it's very frequent that you might want to share designs or share settings across 21
different screens. 22
So instead of having it live inside a particular file or a particular component, it makes sense to create 23
a new file that is going to be a Dart file and it's going to be called constants. 24
And this is going to hold all of the things that are constant across our app. 25
So that is going to include this labelTextStyle for example. So I'm going to cut it out of here and paste 26
it into here instead. 27
And of course whenever we're using material components we have to import our material library. 28
Now in addition to these text styles, I can also add in all of my color constants from over here. And we 29
can paste that into this file instead. 30
And now I have all of my constants together in one place and I can refer to it from any of my files 31
simply by importing the constants. 32
So at the moment you can see that we have some errors here because it doesn't know about labelTextStyle 33
anymore since we moved it out. 34
But as soon as I hit import and I import my constants.dart file, then that error goes away and it's 35
able to see into here and see what text style it should apply to that label. 36
Now similarly on my input page, I've got errors all over the place because it doesn't know about this 37
activeCardcolor and inactiveCardColor. 38
So let's go ahead and import our constants into this file as well. 39
So now it's a good time to mention that the naming convention for these constants usually start out 40
with a K. 41
So we can refactor our code to meet that style. So we can right click on each of our constants and we 42
can go to refactor and rename which is our friend that is going to search for all the places where we 43
use this constant and rename it all in one go. 44
So instead of calling it bottomContainerHeight, the convention is to start with a K, K for constant 45
because C is used for a lot of other things. 46
So K for constant and then we're going to start off with a capital B. 47
So K constant, bottomContainerHeight we're going to refactor that and now you can see everywhere where 48
we use that, it's now been refactored automatically. 49
So I'm just gonna go ahead and do the same for all my other constant. And from now on when I'm creating 50
new constants in my constants.dart, I'll be using that naming convention. 51
All right. 52
So here are all my constants renamed and they're going to be renamed everywhere where they're used. 53
Now why did I go through all that trouble of renaming all my constants? 54
Well whenever you're trying to pick out a color or a text style from your constants file, you start out 55
by typing K. And now Android Studio is intelligent enough to show you all of the relevant constants 56
that you might want to use at this point. So you can see that there's kBottomContainerColor, kBottom 57
ContainerHeight and there's also constants that Flutter has defined such as the kMaterialEdges, k 58
MaterialListPadding, 59
so this way all the constants can be searched easily in one go. 60
So let's change that back to kActiveCardColor. And every time you're looking for a constant you get 61
that dropdown list to select from, which is much easier than trying to remember what the name of your 62
constants at the top of the file is especially once this list gets a bit longer and your app gets more 63
complex. 64
All right. 65
So back to our reusableCard which now has a text widget and I'm now able to give it a additional style 66
which is going to be the kLabelTextStyle, 67
so I can simply select that. 68
And now you should be able to see in the app we've got the same styling for that height text. But our 69
card has now resized to the size of its child. 70
So remember that the way that containers work is that if they have no children, they'll try to size themselves 71
to be as large as the parent allows, 72
and in this case it was stretched to the full width of the column. But once it receives the child, it 73
will try to resize itself to fit the size of the child. 74
So that's why my card has now shrunken in width. 75
But this is relatively easy to fix. 76
We can simply go to our main column at the very top and we can change it's crossAxisAlignment to our 77
friend which is crossAxisAlignment.stretch. And now it will stretch all of its children to take 78
up the full width of the column no matter the size of the child. In addition to the height label, I also 79
want to add a value for the selected height so that when the user toggles the slider it will change 80
as they move it around. 81
So I now need to add a number and a bit of text that says cm or centimeter. In order to do that, 82
I'm going to add a row under my text widget right here. So my row widget is going to have just two children 83
and both of them are going to be text widgets because one of them is going to display the height that's 84
selected and the second one is just going to display the word cm. My text widget is going to contain 85
some numbers. 86
So let's say it starts out with maybe the string 180. And then it's going to have some styling. And I 87
want this to be super large 88
so my textile is going to have a font size of maybe 50 and it's also going to have a super super heavy 89
font weight. So I'm going to set it as probably w900 which is the heaviest weight possible. 90
The heavyweight champion of my font. 91
So now if we take a look at our design, you can see that the number is pretty much as thick as my icons 92
and I quite like that consistency. So I'm probably going to be using this number style across the other numbers 93
that are on the screen, 94
so for example when I create the weight card or the age card. So it makes sense to turn this into a constant. 95
Pause the video and create a constant from this text style and replace all of this code here. 96
All right. 97
So of course we're going to create our constants in our brand new constants.dart file. 98
We're going to start out with the keyword const 99
and we're going to name it using the K convention. 100
So this is going to be k and I'm going to call it numberTextStyle. 101
You can call yours anything you wish. 102
And I'm going to replace it with what I have here which is my text style. 103
And over here I'm going to call it NumberTextStyle. 104
And now that should refer to our file over here. 105
And I'm going to paste in that text style I had from before. 106
So now I can reuse this one and this one across a lot of my design components. 107
And it keeps my code relatively simple and straightforward on my main page. Now that I've created my 108
number, 109
let's go ahead and add the second text widget in my row which is going to simply just say cm. 110
Now if you're from the States and you want to have imperial as your unit then feel free to change the 111
numbers or the units as you wish. 112
Now, that cm is going to have the same text style as my male, female or height labels. 113
Simple enough, I can simply tap into the style property, add my k for constant and select my label text style. 114
So now I have 180 and I have my cm. 115
Now you'll notice that everything is kind of all over the place at the moment. My height label is all 116
squished right at the top 117
and my number row is all the way to the left. 118
And it doesn't look very good. 119
So let's bring all of our components into the center of our column by changing the mainAxisAlignment 120
of our column to center. 121
And this should bring everything down into the middle of the column. 122
Now let's also make our row centered along the main axis 123
so it brings it right into the middle, by going over to our row and changing our mainAxisAlignment 124
to center as well. 125
And now everything's at least in the middle. 126
But there's one other thing that I would really like to have, which is for the cm or the centimeter 127
or whatever units you chose, to be on the same baseline as my number here. 128
So that way it looks like it's actually a 180 cm rather than sort of having the unit floating around 129
somewhere in the middle. 130
And you can see in the final design that's exactly what I have and it looks a lot nicer when it's aligned 131
all to the same baseline. 132
Now we can do this quite easily by simply adding a crossAxisAlignment to our row. 133
So remember that the main axis is along the length of the row and the cross axis is along the short 134
side, 135
so the width of the row. 136
And we're going to set our crossAxisAlignment to one of the options which sounds very very much like 137
what we want, which is .baseline. 138
And in this case, it's going to place the children along the cross axis such that their base lines match. 139
Let's go ahead and select that. 140
Now at this point if we hit save and we tried to look at our design, you'll see that it will break. 141
And the reason it tells us seems kind of cryptic. It's saying if we are going to change our cross axis 142
alignment to baseline, then we actually have to have a text baseline property set to something and it 143
can't be null. 144
How do I know this? 145
Well you can simply take this error message from our run panel and pass it through our friend which 146
has Google of course. And we can search to see if this has already occurred for somebody else. 147
So very often when you get error codes with Flutter, you can search for it in Google and it'll come 148
up in Stack Overflow or in the actual Flutter GitHub repository issue area. And here somebody actually 149
from the Flutter team has provided the solution here saying that you have to specify the textBaseline 150
argument if you want the baseline to be aligned, so that they know which baseline to line against and 151
maybe in the future, they're going to plan on making that message better. 152
And this is really one of the great things about the Flutter community. It's in development but your 153
input and also all the other developers experiences are contributing to the final product. 154
And day by day fixes will be made and changes will happen and it's just going to get better. 155
So let's try and implement that. 156
So they're talking about something called a textBaseline argument. 157
So where we have our crossAxisAlignment for our row, if we go ahead we can see that if we click on 158
CONTROL + J or CONTROL + Q on Windows, you can see that one of its properties is exactly that text 159
base line. 160
So let's try and set it so that our crossAxisAlignment.baseline will work. 161
So let's add textBaseline and then we can start typing TextBaseline with a capital T. And we can 162
now see that we have two options either alphabetic which is for alphabetic characters or ideographic 163
which is for basically graphical characters. 164
So we want alphabetic and now if we hit save, you can see that our error goes away and our row is now 165
beautifully aligned across the baseline. Pretty neat. 166
Now if you're working on any sort of development be it web or mobile or Flutter, you'll inevitably encounter 167
errors and warnings and problems. But just know that there's a strong community behind you who will be 168
able to help you out and you are not alone. 169
And in most cases the things that you've experienced, other people have experienced too and they've probably 170
come across a solution already. All right. 171
So we've solved our labels and our numbers, and it's now time to add a slider. Now Flutter has a widget 172
called a slider and it will implement a material design slider. And if we search for it, you can see that 173
this is roughly what it looks like. It's got a small round thumb which you can move around and it's got 174
one active side and one inactive side. 175
And when you click on it, it's got this sort of outline that pops up. And that looks very similar to what 176
we want to implement in our design. 177
So let's go ahead and implement it so that we can create this design. Now right below where I have my 178
row ending here, 179
I'm going to add a slider widget. And the slider widget has a number of properties such as a onChanged 180
callback. 181
So it's expecting a method that takes a double as an input and outputs void. 182
So whenever you see an arrow as one of the properties, you always know that this is expecting a function. 183
And it can also detect when a change starts or when the change ends. 184
So that means when the user starts dragging and ends dragging, you can also set the minimum position 185
and the maximum position. 186
So maybe if you're setting a temperature, you'll go from 0 to 30, but maybe for other users your scale 187
will be different so you can determine that. 188
And then there's the number of divisions you might want, a label for the slider and then there's the 189
active color and the inactive color. 190
So the active color, the documentation says, is the color to use for the proportion of the slider track 191
that's active. 192
And if you click on it, it gives you a little bit more detail. 193
And it shows that the active side is actually the side between the thumb, 194
so the circle in the middle, and the minimum value. 195
So basically that's going to be the color on the left here. 196
And then the inactive color is the one on the right. 197
So let's go ahead and implement some of these properties so that we can bring our slider to life. So 198
first things first, we're going to provide a value. Now, 199
the value of our slider is going to be the height that the user selected. 200
And we also want it to show up inside here, in this number. 201
So let's go ahead and create another property for our class that's going to be a integer and it's 202
going to be called height. And we'll start it off with a value of 180. 203
Now this can't be final or constant because it's going to change all the time and every time the user 204
slides on that slider. Instead of hardcoding 180 in here, we're going to be putting the value of the 205
height in here. 206
But because the text widget needs a string as the data, we can't simply just put a number in here. And 207
it tells us that type it can't be assigned to type string. 208
So let's go ahead and convert it by writing height.toString. 209
So now we have a string that's converted from our number and you can always convert numbers to strings 210
or ints to doubles. But if you want to do the opposite way then it's a little bit more tricky because 211
A B and C don't map directly to a number right? 212
But this is easy to do. 213
So now for our slider, the value is going to be our height. And we're going to get another incompatible 214
issue here. 215
It's going to tell us that the argument type int can't be assigned to the parameter type double, and 216
that's because the value is expecting a double to go in there as the value. 217
So what we can do is we can use again our trusty .notation to change it to a double. 218
So again super easy conversion and easily doable. 219
So now our height is going to be displayed as the value of the slider. 220
So that's the starting value basically. Now, 221
next we're going to define the scale for our height and most people are not zero centimetres tall hopefully. 222
I guess unless you're like a single celled organism or something, but they're probably not going to be 223
using our app. 224
So let's start off with a minimum value of maybe let's say 120, and maybe a max value of say, I don't know, 220 225
right? 226
So because we're in centimeters, we're talking about 1 meter 20 and 2 meter 20. You can obviously change 227
your scale if this doesn't make sense at all. 228
If all the people that you live around are like three meters tall, then feel free to change the scale. 229
Again these are things that work really well as constants. 230
So it might make sense to add it into our constants over here. 231
But for now I'm just going to leave it in here to make it easy to see how our slider is being built 232
out. 233
But feel free to create a constant and you'll be able to easily hit up one file and update those constants 234
if needed. 235
So you can see that our slider is still being highlighted as yellow, 236
and whenever that happens you also get a line in the right telling you what the warning is about. 237
You also get a little yellow box telling you there's problems or there's warnings found. 238
So in this case if we hover over it, it tells us that the parameter or the property onChanged is required. 239
So at the moment, we're still missing one more property which is the onChanged. 240
And you can see that just as I was typing over here, that it's telling us that it expect a function something 241
that takes a double as an input and returns void. 242
So we have to pass in a function into the slider just as we did for our reusableCard. In our onChanged, 243
instead of just having an anonymous function with no inputs, it actually expects a double value in there. 244
And that value is going to be the new value of the slider. 245
So you can see that in the docs it tells us that the onChanged is called during a drag when the user is 246
selecting a new value by dragging. 247
And if we click on it to see more information, you can see that the slider will pass the new value to 248
the callback and we will be able to tap into that new value inside the anonymous function. 249
So this is how they're recommending us to use the onChanged property. 250
So let's go ahead and do that. In our onChanged property, it's going to take a double. 251
And we're going to call it newValue. 252
And this is going to be the value that will be passed to us from the slider when the slider gets changed 253
by the user. 254
And then inside the curly braces here, we'll be able to tap into that newValue and we'll be able to use 255
it for our purposes of changing the height. 256
Now if we go ahead and hit save and when we run it, we can see it vaguely on screen but it's so dark 257
that we actually can't differentiate it from the background. 258
So let's go ahead and add some color to it. 259
Let's add an activeColor which is going to be a custom color as usual. 260
And in this case it's going to be 0xFFEB1555, and this will turn the left side pink and let's 261
go ahead and add a color for the right side as well. 262
So the inactiveColor and this is going to be 0xFF8D8E98. 263
So now we have a gray on the right and a pink on the left. 264
Now at this stage something very curious happens. When I click onto the handle of my slider and I drag 265
it around, because we're going to print the new value that the slider is at, we're going to see it inside 266
our console. 267
So you'll see the value change and I can go all the way down to the very bottom which is 120 and go 268
back up to 220. 269
But the slider itself is not really doing anything on screen right? It's not animating, it's not moving 270
at all. It looks like it's completely stuck. If it wasn't for all of these readings that I'm getting by 271
printing the new value, I would have thought that my slider is completely not working. 272
Why is this? 273
Well if we head into the documentation and we look at the onChanged property, you can see that it says 274
that the slider passes the new value to the callback. 275
So when I move my toggle around, it will pass the new value into my callback through this input here. 276
So I get access to that new value which is being printed inside my console. But it does not actually 277
change the state of my slider until the parent widget rebuilds the slider with the new value. 278
So how do we rebuild the parents slider with the new value? 279
Well the callback, 280
so everything in between these curly braces, should update the status of the parent using set state. 281
So the parent gets rebuilt in the way that they've shown here. 282
So for example here in their onChanged, they have a new value being passed into this callback here and 283
then that new value is used to update the value of the slider which is right here. 284
So this is how we're able to update the appearance of the slider. 285
Let's give it a go in our code as well and actually get our slider moving and animating. Instead of printing 286
the new value, 287
we're going to set the height property which is a mutable or a variable property that we have in here. 288
And it's also an integer which starts out at 180. 289
Once the slider is changed, we're going to set the height to equal the new value. 290
But the problem is that new value is a double 291
but height is an integer. 292
So let's go ahead and round it up to an integer so that can be turned into the nearest whole number. 293
And then all we have to do is call set state and make sure that the state of our slider gets updated 294
based on this height. 295
Now if we hit save and we check out our handiwork, then you can see our slider's moving and our text which 296
displays the height also, is also updating. 297
Perfect. 298
We've got all of our functionality of our slider card now enabled.
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.