diff --git a/flutter b/flutter index e4ebcdf6f4..20e59316b8 160000 --- a/flutter +++ b/flutter @@ -1 +1 @@ -Subproject commit e4ebcdf6f4facee5779c38a04d91d08dc58ea7a4 +Subproject commit 20e59316b8b8474554b38493b8ca888794b0234a diff --git a/src/_assets/image/codelab/layout/businesscarddisplay0.png b/src/_assets/image/codelab/layout/businesscarddisplay0.png deleted file mode 100644 index 209f3b3e2d..0000000000 Binary files a/src/_assets/image/codelab/layout/businesscarddisplay0.png and /dev/null differ diff --git a/src/_assets/image/codelab/layout/Completedbusinesscarddisplay1.png b/src/_assets/image/codelab/layout/businesscarddisplay1.png similarity index 100% rename from src/_assets/image/codelab/layout/Completedbusinesscarddisplay1.png rename to src/_assets/image/codelab/layout/businesscarddisplay1.png diff --git a/src/_assets/image/codelab/layout/Completedbusinesscarddisplay2.png b/src/_assets/image/codelab/layout/businesscarddisplay2.png similarity index 100% rename from src/_assets/image/codelab/layout/Completedbusinesscarddisplay2.png rename to src/_assets/image/codelab/layout/businesscarddisplay2.png diff --git a/src/_assets/image/codelab/layout/Completedbusinesscarddisplay3.png b/src/_assets/image/codelab/layout/businesscarddisplay3.png similarity index 100% rename from src/_assets/image/codelab/layout/Completedbusinesscarddisplay3.png rename to src/_assets/image/codelab/layout/businesscarddisplay3.png diff --git a/src/_assets/image/codelab/layout/Completedbusinesscarddisplay4.png b/src/_assets/image/codelab/layout/businesscarddisplay4.png similarity index 100% rename from src/_assets/image/codelab/layout/Completedbusinesscarddisplay4.png rename to src/_assets/image/codelab/layout/businesscarddisplay4.png diff --git a/src/_assets/image/codelab/layout/businesscarddisplay5.png b/src/_assets/image/codelab/layout/businesscarddisplay5.png deleted file mode 100644 index a5f654d0fd..0000000000 Binary files a/src/_assets/image/codelab/layout/businesscarddisplay5.png and /dev/null differ diff --git a/src/docs/codelabs/index.md b/src/docs/codelabs/index.md index 13b8796a82..a0a63e4aab 100644 --- a/src/docs/codelabs/index.md +++ b/src/docs/codelabs/index.md @@ -4,7 +4,7 @@ description: "Codelabs help you quickly get started programming Flutter." --- -#### [Basic Flutter layout](/docs/codelabs/layout-basics) +#### [Basic Flutter layout concepts](/docs/codelabs/layout-basics) Use DartPad in a browser (no need to download Flutter or Dart!) to learn the basics of creating a Flutter layout. diff --git a/src/docs/codelabs/layout-basics.md b/src/docs/codelabs/layout-basics.md index 7c8613c196..13a5455d53 100644 --- a/src/docs/codelabs/layout-basics.md +++ b/src/docs/codelabs/layout-basics.md @@ -1,427 +1,646 @@ --- -title: "Codelab: Basic Flutter layout" -description: "A codelab that uses DartPad2 to teach Flutter layout concepts." -toc: false ---- - -{{site.alert.note}} - The embedded editors use an experimental version of DartPad. - If you find a DartPad bug or have suggestions for DartPad, - please [create a DartPad - issue](https://github.com/dart-lang/dart-pad/issues/new) - by clicking the bug icon at the top right of this page. +title: "Basic Flutter layout concepts" +description: "A codelab that teaches basic Flutter layout concepts through DartPad examples and exercises." +toc: true +--- +Welcome to the Flutter layout codelab, +where you learn how to build a Flutter UI without downloading and installing Flutter or Dart! + +{{site.alert.important}} + This codelab covers basic Flutter layout concepts using an experimental code editor called DartPad. + DartPad hasn't been fully tested on all browsers. + If you experience any difficulties while using DartPad on a specific browser, + please create a [DartPad issue](https://github.com/dart-lang/dart-pad/issues/new) + and specify which browser you're using in the issue title. {{site.alert.end}} -{{site.alert.note}} - This codelab is currently being developed and tested - with Chrome. There might be (in the short term) features that - work in some browsers and not others. If you encounter any, please - [create a DartPad issue](https://goo.gle/flutter_web_issue), - labeling the issue with `platform-web`. +Flutter is different from other frameworks because its UI is built in code, +not (for example) in an XML file or similar. +Widgets are the basic building blocks of a Flutter UI. +As you progress through this codelab, +you'll learn that almost everything in Flutter is a widget. +A widget is an immutable object that describes a specific part of a UI. +You'll also learn that Flutter widgets are composable, meaning, +that you can combine existing widgets to make more sophisticated widgets. +At the end of this codelab, +you'll get to apply what you've learned +into building a Flutter UI that displays a business card. + +**Estimated time to complete this codelab: 45-60 minutes.** + +## Row and Column classes +`Row` and `Column` are classes that contain and lay out widgets. +Widgets inside of a `Row` or `Column` are called *children*, +and `Row` and `Column` are referred to as *parents*. +`Row` lays out its widgets horizontally, +and `Column` lays out its widgets vertically. + +#### Example: Creating a Column +{:.no_toc} +{{site.alert.secondary}} +{:.no_toc} + The following example displays the differences between a `Row` and `Column`. + + **1.** Click the **Run** button. + + **2.** In the code, change the `Row` to a `Column`, and run again. {{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/4e11c4a7ec824685f963f25d7c30ba0b +{% endcomment %} + + +## Axis size and alignment + +So far, the `BlueBox` widgets have been squished together +(either to the left or at the top of the UI Output). +You can change how the `BlueBox` widgets are spaced out using the axis size and alignment properties. + +### mainAxisSize property + +`Row` and `Column` occupy different main axes. +A `Row`'s main axis is horizontal, +and a `Column`'s main axis is vertical. +The `mainAxisSize` property determines how much space a `Row` and `Column` can occupy on their main axes. +`mainAxisSize` has two possible values: + +`MainAxisSize.max` +: `Row` and `Column` occupy all of the space on their main axes. +If the combined width of their children is +less than the total space on their main axes, +their children are laid out with extra space. + +`MainAxisSize.min` +: `Row` and `Column` only occupy enough space on their main axes +for their children. Their children are laid out without extra space +and at the middle of their main axes. + +{{site.alert.tip}} + `MainAxisSize.max` is the `mainAxisSize` property's default value. + If you don't specify another value, + the default value is used, + as shown in the previous example. +{{site.alert.end}} +#### Example: Modifying axis size +{:.no_toc} +{{site.alert.secondary}} +{:.no_toc} -`Row` and `Column` are two very important widgets in the Flutter universe. -Want to put a `Text` widget with a label next to another `Text` -widget with the corresponding value? Use a `Row`. -Want to present multiple pairs of labels and values? -That's a `Column` of `Row`s. Forms with several fields, -icons next to menu choices, buttons next to -search bars, these are all places where `Row`s and `Column`s are used, - -This codelab walks you through how `Row`s and `Column`s work. -Because they're so similar, once you're done learning about -`Row`s, the codelab mostly shows you how all the same concepts apply -to `Column`s. There are inline editors -along the way so you can play around and test your knowledge. - -### Start with a Row and some children - -The whole point of a `Row` or `Column` is to contain -other widgets, known as children. In a `Row`, children -are arranged horizontally from first to last in accordance -with text direction. If your device is set to -English or another left-to-right language, it starts from the left. -If you're using Arabic or another right-to-left language, it starts -on the right and moves left. - -#### Code example - -Below is a widget called `MyWidget` that builds a single `Row`. -Try adding three `BlueBox` widgets to its list of children. - - - -### Main axis size - -The main axis of a `Row` is the horizontal one (for -`Column`s, it's the vertical axis). Each `Row` has a -property called `mainAxisSize` that determines how much space -it should take along that axis. By default, -`mainAxisSize` is set to `MainAxisSize.max`, which -causes a `Row` to take up all the available horizontal -space. You can use `MainAxisSize.min` to direct a `Row` -widget to take up as little space as possible. - -#### Code example - -Here's the example you just finished. Try setting the `Row`'s -`mainAxisSize` property to `MainAxisSize.min` and see what happens. - - - -### Main axis alignment - -If you've set the `mainAxisSize` of a `Row` to the minimum, -there won't be any extra room beyond what the children use. -If you've set it to `max`, though, the `Row` might have some -additional space lying around. You can use the `mainAxisAlignment` -property to control how the `Row` aligns its children within that space. - -There are six different values available in the `MainAxisAlignment` enum: - -* `MainAxisAlignment.start`
- Place all children as close to the start of the `Row` as possible - (for left-to-right rows, this is the left side). - -* `MainAxisAlignment.end`
- Place all children as close to the end of the `Row` as possible. - -* `MainAxisAlignment.center`
- Group the children together in the center of the `Row`. - -* `MainAxisAlignment.spaceBetween`
- Any extra space is divided evenly and used to make gaps between the children. - -* `MainAxisAlignment.spaceEvenly`
- Just like `spaceBetween`, except the spots before the first child - and after the last one also count as gaps. - -* `MainAxisAlignment.spaceAround`
- Just like `spaceEvenly`, only the first and last gaps get 50% of the - amount used between children. - -#### Code example - -The row below has its `mainAxisAlignment` set to start. Try changing it to the -other values and re-running the code to see how things move around. - - -### Cross axis alignment + The following example explicitly sets `mainAxisSize` to its default value, `MainAxisSize.max`. -The cross axis for `Row` widgets is the vertical axis, -and you can use the `crossAxisAlignment` property to -control how children are positioned vertically. -The default value is `CrossAxisAlignment.center`, -but there are five options in total: + **1.** Click the **Run** button. -* `CrossAxisAlignment.start`
- Children are aligned at the start of the `Row`'s vertical space - (by default, the top is considered to be the start, - though you can change that via the `verticalDirection` property). + **2.** Change `MainAxisSize.max` to `MainAxisSize.min`, and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/d852e4f07d6c87600fe8e0f186c7a31b +{% endcomment %} + -* `CrossAxisAlignment.end`
- Children are aligned at the end of the `Row`'s - vertical space (by default, that means the bottom). +### mainAxisAlignment property -* `CrossAxisAlignment.center`
- Children are centered with respect to the vertical axis. +When `mainAxisSize` is set to `MainAxisSize.max`, +`Row` and `Column` might lay out their children with extra space. +The `mainAxisAlignment` property determines how `Row` and `Column` +can position their children in that extra space. + `mainAxisAlignment` has six possible values: -* `CrossAxisAlignment.stretch`
- Children are forced to have the same height as the - `Row` itself, filling all the vertical space. +`MainAxisAlignment.start` +: Positions children near the beginning of the main axis. +(Left for `Row`, top for `Column`) -* `CrossAxisAlignment.baseline`
- Children are aligned by their baselines (more on this one below). +`MainAxisAlignment.end` +: Positions children near the end of the main axis. +(Right for `Row`, bottom for `Column`) -#### Code example +`MainAxisAlignment.center` +: Positions children at the middle of the main axis. -This `Row` has two small children and one big one. Its -`crossAxisAlignment` property is set to center, the default. -Try changing it to the other values and re-running the code to -see how things move around. +`MainAxisAlignment.spaceBetween` +: Divides the extra space evenly between children. -A word of warning: `CrossAxisAlignment.baseline` requires -that another property be set as well, so you -will see an error if you try that one. -Don't worry, though—it's covered in the next section. +`MainAxisAlignment.spaceEvenly` +: Divides the extra space evenly between children and before and after the children. - +`MainAxisAlignment.spaceAround` +: Similar to `MainAxisAlignment.spaceEvenly`, +but reduces half of the space before the first child and after the last child +to half of the width between the children. -### Baseline alignment +#### Example: Modifying main axis alignment +{:.no_toc} +{{site.alert.secondary}} -Sometimes it's handy to align widgets containing text not by their -overall bounds, but by the baselines used by their characters. -That's what `CrossAxisAlignment.baseline` is for. You -can use it in combination with a `Row`'s `textBaseline` -property (which indicates which baseline to use) to align a -`Row`'s children along their baselines. + The following example explicitly sets `mainAxisAlignment` to its default value, + `MainAxisAlignment.start`. -Note that if you set a `Row`'s `crossAxisAlignment` property -to baseline without setting `textBaseline` at the same -time, your widgets will fail to build. + **1.** Click the **Run** button. -#### Code example + **2.** Change `MainAxisAlignment.start` to `MainAxisAlignment.end`, and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/cb8abed13f90a6a0c7a0ada6f15a09c9 +{% endcomment %} + +{{site.alert.tip}} + Before moving to the next section, change `MainAxisAlignment.end` to another value. +{{site.alert.end}} -This row contains three `Text` widgets with different font -sizes. Try changing the `crossAxisAlignment` -property to `baseline`, and experiment with different -values for `textBaseline` as well (there's an enum called -`TextBaseline` that contains the valid baseline values). +### crossAxisAlignment property - +The `crossAxisAlignment` property determines +how `Row` and `Column` can position their children on their cross axes. +A `Row`'s cross axis is vertical, and a `Column`'s cross axis is horizontal. +Most of the `crossAxisAlignment` property's values only work with the `Row` class. +`crossAxisAlignment` has five possible values: -### Flexible children +`CrossAxisAlignment.start` +: Positions children near the top of the cross axis. (`Row` only) -So far, all the widgets used as children in examples have -had a fixed size. It's possible, though, for a -`Row` to have children that flex, -and adapt to the available space. In order to -understand how this works, -it's best to take a look at how `Row`s size themselves and -their children: +`CrossAxisAlignment.end` +: Positions children near the bottom of the cross axis. (`Row` only) -1. First, the `Row` asks all of its children with fixed - sizes how big they'd like to be. -1. Next, it calculates the remaining space in its main - axis (horizontal). -1. Then it divides up that remaining space among its - flexible children according to their flex factors. - The flexible children can use some or all of the space - they're offered. -1. At that point, the `Row` knows how big all of its - children are, and can align them using the same axis - size and alignment properties you've seen so far. +`CrossAxisAlignment.center` +: Positions children at the middle of the cross axis. (`Row` only) -Most widgets are considered to be of a fixed size. -You can change that by wrapping them in a `Flexible` -widget. `Flexibles` have two important properties: -a `flex` factor that determines how much of the remaining -space they get in comparison to other `Flexibles`, -and a `fit` property that determines whether their child -is forced to take up all the extra space it's offered. +`CrossAxisAlignment.stretch` +: Stretches children across the cross axis. +(Top-to-bottom for `Row`, left-to-right for `Column`) -#### Code example +`CrossAxisAlignment.baseline` +: Aligns children by their character baselines. (`Text` class only, and requires that the `textBaseline` property is set to `TextBaseline.alphabetic`. See the [Text class](#text-class) section for an example.) -Try wrapping the middle box in this row with a `Flexible` -widget that has a `flex` factor of 1 and its `fit` -property set to `FlexFit.loose`. Afterward, -try changing the fit to tight and see what happens. +#### Example: Modifying cross axis alignment +{:.no_toc} +{{site.alert.secondary}} + The following example explicitly sets `crossAxisAlignment` to its default value, + `CrossAxisAlignment.center`. -This combination (a `flex` factor of 1 and a tight `fit`) -is so popular, there's a whole widget just to make -using them easier: `Expanded`. + To demonstrate cross axis alignment, `mainAxisAlignment` is set to + `MainAxisAlignment.spaceAround`, and `Row` now contains a `BiggerBlueBox` widget + that is taller than the `BlueBox` widgets. - + **1.** Click the **Run** button. -### Flex factors + **2.** Change `CrossAxisAlignment.center` to `CrossAxisAlignment.start`, and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/70a6eb88f13019eec349a57bc4fd5fe0 +{% endcomment %} + +{{site.alert.tip}} + Before moving to the next section, change `CrossAxisAlignment.start` to another value. +{{site.alert.end}} -If more than one child of a `Row` or `Column` has a -flexible size, the available space is allotted to them according to their -`flex` factors. Each child gets space in proportion to their flex -factor divided by the total of all the flex factors of all children: +## Flexible widget - -```dart -remainingSpace * (flex / totalOfAllFlexValues) -``` +As you've seen, the `mainAxisAlignment` and `crossAxisAlignment` properties determine +how `Row` and `Column` position widgets along both axes. +`Row` and `Column` first lay out widgets of a fixed size. +Fixed size widgets are considered *inflexible* because they can't resize +themselves after they've been laid out. -For example, if there are two children with flex factors of 1, -each gets half of the available space. If there -are two children with flex factors of 1 and another child -with a flex factor of 2, the first two -children each get a quarter of the available space, -and the other child gets half. +The `Flexible` widget wraps a widget, so the widget becomes resizable. +When the `Flexible` widget wraps a widget, the widget becomes the `Flexible` widget's child +and is considered *flexible*. +After inflexible widgets are laid out, +the widgets are resized according to their `flex` and `fit` properties.: -#### Code example +`flex` +: Compares itself against other `flex` properties before determining +what fraction of the total remaining space each `Flexible` widget receives. -In this example, all three of the `Row`'s children are `Flexible`. -Try changing their `flex` values and -re-running the code to see how the widgets' sizes adjust. +`fit` +: Determines whether a `Flexible` widget fills all of its extra space. - +#### Example: Changing fit properties +{:.no_toc} +{{site.alert.secondary}} + The following example demonstrates the `fit` property, + which can have one of two values: -### What happens if you run out of space? + `FlexFit.loose` + : The widget's preferred size is used. (Default) -As you just saw, when a `Row` asks one of its `Flexible` -children how big it wants to be, it gives the child -a max width based on its `flex` factor. However, -fixed-size children get no such restriction. This is so -they can determine their own intrinsic size. + `FlexFit.tight` + : Forces the widget to fill all of its extra space. -One side effect is that there's nothing stopping a fixed-size -child from declaring itself to be bigger than the `Row` can support. -When that happens, a flex overflow results. You can -fix it by changing the child widget so that it chooses a smaller size, -or by using a scrolling widget. + In this example, change the `fit` properties to + make the `Flexible` widgets fill the extra space. -#### Code example + **1.** Click the **Run** button. -The `Row` below contains a single widget that's way too wide to fit. Run the -code as-is to see what happens, then try modifying the width of the -`Container` to make it fit. + **2.** Change both `fit` values to `FlexFit.tight`, + and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/ba0f40356d1023066d960f6de2be1a4b +{% endcomment %} + + +#### Example: Testing flex values +{:.no_toc} +{{site.alert.secondary}} + In the following example, `Row` contains one `BlueBox` widget + and two `Flexible` widgets that wrap two `BlueBox` widgets. + The `Flexible` widgets contain `flex` properties with `flex` values set to 1 (the default value). + + When `flex` properties are compared against one another, + the ratio between their `flex` values determines + what fraction of the total remaining space each `Flexible` widget receives. + + ```dart + remainingSpace * (flex / totalOfAllFlexValues) + ``` + + In this example, the sum of the `flex` values (2), + determines that both `Flexible` widgets receive + half of the total remaining space. + The `BlueBox` widget (or fixed-size widget) remains the same size. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/82e4dd24028034ae03ba0ddc71bf59e5 +{% endcomment %} + +{{site.alert.tip}} + Before moving to the next example, try changing the `flex` properties to other values, + such as 2 and 1. +{{site.alert.end}} - +## Expanded widget -### Try using SizedBox to make space +Similar to `Flexible`, the `Expanded` widget can wrap a widget and force the widget to fill extra space. -If you need a specific amount of space between two children of a -`Row`, an easy way to do it is by sticking a `SizedBox` of the -appropriate width in between. +{{site.alert.tip}} + **What's the difference between Flexible and Expanded?** + Use `Flexible` to resize widgets in a `Row` or `Column`. + That way, you can adjust a child widget's spacing + while keeping its size in relation to its parent widget. + `Expanded` changes the constraints of a child widget, + so it fills any empty space. +{{site.alert.end}} -#### Code example +#### Example: Filling extra space +{:.no_toc} +{{site.alert.secondary}} + The following example demonstrates how the `Expanded` widget forces its child widget to fill extra space. -Trying making some space between these two list items by placing a -`SizedBox` with a `width` of 100 between them. + **1.** Click the **Run** button. - + **2.** Wrap the second `BlueBox` widget in an `Expanded` widget. -### Spacers expand to make space + For example: -`Spacers` are another convenient way to make space between -items in a `Row`. They're flexible, and expand to fill any -leftover space. + ```dart + Expanded(child: BlueBox(),), + ``` + **3.** Select the **Format** button, and run again. -#### Code example +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/77021d2ed15f9ece850de15e73c47526 +{% endcomment %} + + +## SizedBox widget + +The `SizedBox` widget can be used in one of two ways when creating exact dimensions. +When `SizedBox` wraps a widget, +it resizes the widget using the `height` and `width` properties. +When it doesn't wrap a widget, +it uses the `height` and `width` properties to create empty space. +#### Example: Resizing a widget +{:.no_toc} +{{site.alert.secondary}} + The following example wraps the middle `BlueBox` widget inside of a + `SizedBox` widget and sets the `BlueBox`'s width to 100 logical pixels. + + **1.** Click the **Run** button. + + **2.** Add a `height` property equal to 100 logical pixels inside the `SizedBox` widget, and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/6582851e85b57180ff5321f814fabb81 +{% endcomment %} + -Try adding a `Spacer` in between the first and second children of the -`Row` below. +#### Example: Creating space +{:.no_toc} +{{site.alert.secondary}} + The following example contains three `BlueBox` widgets and one `SizedBox` widget that separates the first and second `BlueBox` widgets. The `SizedBox` widget contains a `width` property equal to 50 logical pixels. - + **1.** Click the **Run** button. -### Wait, wasn't I going to learn about Columns, too? + **2.** Create more space by adding another `SizedBox` widget (25 logical pixels wide) + between the second and third `BlueBox` widgets, and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/19ead147ab5c7668d7d32e1cfed90097 +{% endcomment %} + -Surprise, you already have! `Row`s and `Column`s do the -same job, just in different dimensions. The main -axis of a `Row` is horizontal, and the main axis of a -`Column` is vertical, but they both size and position their -children in the same way. They even share a base class, -`Flex`, so everything you've learned about `Row`s -applies to `Column`s as well! +## Spacer widget -#### Code example +Similar to `SizedBox`, the `Spacer` widget also can create space between widgets. -Here's a `Column` with some children of various sizes and its most important -properties set. Try fiddling around with them and you'll see that the -`Column` works like a vertical `Row`. +{{site.alert.tip}} + **What's the difference between SizedBox and Spacer?** + Use `Spacer` when you want to create space using a `flex` property. + Use `SizedBox` when you want to create space + using a specific number of logical pixels. +{{site.alert.end}} - +#### Example: Creating more space +{:.no_toc} +{{site.alert.secondary}} + The following example separates the first two `BlueBox` widgets using + a `Spacer` widget with a `flex` value of 1. -### Putting it all together + **1.** Click the **Run** button. -Now that you're versed in `Row`s, `Column`s, and the -important properties of both, you're ready to practice -putting them together to build interfaces. The next few -examples guide you through the construction -of a business card display. + **2.** Add another `Spacer` widget (also with a `flex` value of 1) + between the second and third `BlueBox` widgets. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/bfc367aefde35e02ea5283efdbf58e60 +{% endcomment %} + -#### Code example +## Text widget -Every business card needs a name and a title, so start with that. +The `Text` widget displays text and can be configured +for different fonts, sizes, and colors. -* Add a `Column` widget -* Add two text widgets to the `Column`'s list of children: - * The first should be a name (a short one is easier to - fit into the small window) and use the `headline` style: +#### Example: Aligning text +{:.no_toc} +{{site.alert.secondary}} + The following example displays "Hey!" three times, + but at different font sizes and in different colors. + `Row` specifies the `crossAxisAlignment` and `textBaseline` properties. - -```dart -style: Theme.of(context).textTheme.headline -``` + **1.** Click the **Run** button. - * The second text widget should say `Experienced App Developer` - and use the default style (leave the `style` property out entirely). + **2.** Change `CrossAxisAlignment.center` to `CrossAxisAlignment.baseline`, and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/0ff109090b99ef1873d9fad501b2bc86 +{% endcomment %} + + +## Icon widget + +The `Icon` widget displays a graphical symbol +that represents an aspect of the UI. +Flutter is preloaded with icon packages for +[Material](https://api.flutter.dev/flutter/material/MaterialApp-class.html) and +[Cupertino](https://api.flutter.dev/flutter/cupertino/CupertinoApp-class.html) applications. + +#### Example: Creating an Icon +{:.no_toc} +{{site.alert.secondary}} + The following example displays the widget `Icons.widget` from the + [Material Icon library](https://api.flutter.dev/flutter/material/Icons-class.html) in red and blue. + + **1.** Click the **Run** button. + + **2.** Add another `Icon` from the + [Material Icon library](https://api.flutter.dev/flutter/material/Icons-class.html) + with a size of 50. + + **3.** Give the `Icon` a color of `Colors.amber` from the + [Material Color palette](https://api.flutter.dev/flutter/material/Colors-class.html), + and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/01688fca8c13f85d93078054af2e858b +{% endcomment %} + -* Set the `Column`'s `crossAxisAlignment` to start, so - that the text widgets are start-aligned rather than centered. +## Image widget -* Set the `Column`'s `mainAxisSize` to `MainAxisSize.min`, - so the card won't expand to the full height of the window. +The `Image` widget displays an image. You either can reference images using a URL, +or you can include images inside your app package. Since DartPad can't package an image, +the following example uses an image from the network. - +#### Example: Displaying an image +{:.no_toc} +{{site.alert.secondary}} + The following example displays an image that's stored remotely on [GitHub](https://github.com/flutter/website/tree/master/examples/layout/sizing/images). + The `Image.network` method takes a string parameter that contains the image's URL. -Business cards often have an icon or logo in the top-left corner, -so the next step is to add one to yours. Start by wrapping the -`Column` you just created with a `Row` widget: + In this example, `Image.network` contains a short URL. - -```dart -Row( - children: [ - Column( … ), // <- This should be the Column you made in the previous step - ], -); -``` + **1.** Click the **Run** button. -Now you can add the `Icon`: + **2.** Change the short URL to the actual URL: -* Above your `Column` in the `Row`'s list of children, - add a `Padding` widget. - * Set its `padding` to `const EdgeInsets.all(8)`. - * For the child of the `Padding` widget, use an `Icon`. - * You can use any icon resource you want, though `Icons.account_circle` - works nicely. - * Set the `Icon`'s `size` to 50. + `https://github.com/flutter/website/blob/master/examples/layout/sizing/images/pic3.jpg?raw=true` - + **3.** Then change `pic3.jpg` to `pic1.jpg` or `pic2.jpg`, + and run again. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/b6f3084800bd139cdb522b8858bb58b7 +{% endcomment %} + + +## Putting it all together + +You're almost at the end of this codelab. +If you'd like to test your knowledge of the techniques that you've learned, +why not apply those skills into building a Flutter UI that displays a business card! + + ![Completed business card]({% asset codelab/layout/businesscarddisplay1.png + @path%}){:width="400px"}{:.text-center} + +You'll break down Flutter's layout into parts, which is how you'd +create a Flutter UI in the real world. + +In [Part 1](#part-1), +you'll implement a `Column` that contains the name and title. +Then you'll wrap the `Column` in a `Row` that contains the icon, +which is positioned to the left of the name and title. + + ![Completed business card]({% asset codelab/layout/businesscarddisplay2.png + @path%}){:width="400px"}{:.text-center} + +In [Part 2](#part-2), you'll wrap the `Row` in a `Column`, +so the code contains a `Column` within a `Row` within a `Column`. +Then you'll tweak the outermost `Column`'s layout, +so it looks nice. +Finally, you'll add the contact information +to the outermost `Column`'s list of children, +so it's displayed below the name, title, and icon. + + ![Completed business card]({% asset codelab/layout/businesscarddisplay3.png + @path%}){:width="400px"}{:.text-center} + +In [Part 3](#part-3), +you'll finish building the business card display by adding four more icons, +which are positioned below the contact information. + + ![Completed business card]({% asset codelab/layout/businesscarddisplay4.png + @path %}){:width="400px"}{:.text-center} + +### Part 1 +{:.no_toc} + +#### Exercise: Create the name and title +{:.no_toc} +{{site.alert.secondary}} + + Implement a `Column` that contains two text widgets: + + + + For the `Column`, + set `mainAxisSize` to `MainAxisSize.min` + and `crossAxisAlignment` to `CrossAxisAlignment.start`. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/30ccbe0fcf31cc10eafba3aea8ff0697 +{% endcomment %} + + +#### Exercise: Wrap the Column in a Row +{:.no_toc} +{{site.alert.secondary}} + + Wrap the `Column` you implemented in a `Row` that contains the following widgets: + + + + ```dart + Row( + children: [ + Padding( + padding: const EdgeInsets.all(8.0), + child: Icon(Icons.account_circle, size: 50), + ), + Column( ... ), // <--- The Column you first implemented + ], + ); + ``` +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/95dcc1451aea8412669c41eb8a1a5f23 +{% endcomment %} + -Your first `Row` is now complete! There are two more to go, though, -and you need a `Column` to put them in. -Wrap your `Row` with a `Column` widget so that it looks like this: +### Part 2 +{:.no_toc} - -```dart - Column( - children: [ - Row( … ), // <- This should be the Row with your Icon and Text widgets. - ], - ); -``` +#### Exercise: Tweak the layout +{:.no_toc} +{{site.alert.secondary}} + + Wrap the `Row` in a `Column` that has a `mainAxisSize` property set to `MainAxisSize.min` + and a `crossAxisAlignment` property set to `CrossAxisAlignment.stretch`. + The `Column` contains the following widgets: -Then, finish up your new `Column` with these steps: + * A `SizedBox` widget with a height of 8. -* Set the `Column`'s `mainAxisSize` to min - * Otherwise it'll expand to fill the screen! + * An empty `Row` where you'll add the contact information. -* Set the `Column`'s `crossAxisAlignment` to stretch - * This makes all of its children full-width + * A second `SizedBox` widget with a height of 16. -* Add more widgets below your `Row` in the `Column`'s - list of children: - * A `SizedBox` with a height of 8 - * An empty `Row` (no children or other properties) - * A `SizedBox` with a height of 16 - * Another empty `Row` + * A second empty `Row` where you'll add different the four icons (Part 3). - + The `Column`'s list of widgets should be formatted like this, + so the contact information and icons are displayed below the name and title: -There are just a few steps to go now. Next up is the second row. -Add the following to its list of children: + ```dart -* A `Text` widget with a street address like '123 Main Street' -* A `Text` widget with a phone number like '800-123-1234' + ], + ), // <--- Closing parenthesis for the Row + SizedBox(), + Row(), // First empty Row + SizedBox(), + Row(), // Second empty Row + ], + ); // <--- Closing parenthesis for the Column that wraps the Row -If you run the code at this point, you'll see that the two `Text` -widgets are placed right up against each other rather than at -opposite ends of the `Row`, which isn't right. -You can fix this by setting the `Row`'s `mainAxisAlignment` -property to `spaceBetween`, which puts any extra space between -the two `Text` widgets. + ``` - - -The last step is to get those icons in place at the bottom of the card: +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/c3ac34ed8952724a0ecb0af1445c2af8 +{% endcomment %} + + +#### Exercise: Enter contact information +{:.no_toc} +{{site.alert.secondary}} + Enter two `Text` widgets inside the first empty `Row` : + + + + For the first empty `Row`, + set the `mainAxisAlignment` property to `MainAxisAlignment.spaceBetween`. -* Add four `Icon` widgets to the last `Row`'s list of - children. You can use whichever icon resources you - like, but these would be a good way to show that your - imaginary developer focuses on accessibility, - fast development, and multi-platform apps: - * `Icons.accessibility` +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/c5be61116652927c5d92262fce1b5360 +{% endcomment %} + + +### Part 3 +{:.no_toc} +#### Exercise: Add four icons +{:.no_toc} +{{site.alert.secondary}} + Enter the following `Icon` widgets inside the second empty `Row`: + + * `Icons.accessibility` * `Icons.timer` * `Icons.phone_android` * `Icons.phone_iphone` -* Set the `Row`'s `mainAxisAlignment` property to - `MainAxisAlignment.spaceAround` + For the second empty `Row`, + set the `mainAxisAlignment` property to `MainAxisAlignment.spaceAround`. +{{site.alert.end}} +{% comment %} + Gist: https://gist.github.com/datafoya/dae36611fc9af04c4b9d0fbc3429275e +{% endcomment %} + + +## What's next? + +Congratulations, you've finished this codelab! If you'd like to know more about Flutter, here are a few suggestions for resources worth exploring: + +* Learn more about layouts in Flutter by visiting the +[Building layouts](https://flutter.dev/docs/development/ui/layout) page. +* Check out this [list of sample apps](https://github.com/flutter/samples/blob/master/INDEX.md) +that were created using Flutter. +* Visit [Flutter's YouTube channel](https://www.youtube.com/channel/UCwXdFgeE9KYzlDdR7TG9cMw), +where you can watch videos that focus on individual widgets +and see how developers all over the world are using Flutter. - +You also can download Flutter by visiting the [Get started](https://flutter.dev/docs/get-started/install) page. \ No newline at end of file diff --git a/src/docs/development/ui/widgets-intro.md b/src/docs/development/ui/widgets-intro.md index 56438b4add..ed28679fb7 100644 --- a/src/docs/development/ui/widgets-intro.md +++ b/src/docs/development/ui/widgets-intro.md @@ -17,7 +17,7 @@ needed in the underlying render tree to transition from one state to the next. {{site.alert.note}} If you would like to become better acquainted with Flutter by diving - into some code, check out [Basic layout + into some code, check out [Basic Flutter layout codelab](/docs/codelabs/layout-basics), [Building Layouts in Flutter](/docs/development/ui/layout), and [Adding Interactivity to Your Flutter App](/docs/development/ui/interactive).