Today we’re going to work with some of the layout code to see how we can modify/create our own layouts. If you’ve not gone through Learning about Flutter Layouts, you may want to do that first.
We’ll start by creating the basic application. We’ll then modify the title so we know what app we’re building.
return MaterialApp(
title: 'Flutter Layout Demo', // this line changed
theme: ThemeData(
This will just change the title in our HTML page, and similar. To change the app title shown, we’ll do that below.
App Title
To change the app title, modify the MyHomePage line with the title, like you see below.
home: MyHomePage(title: 'Flutter My Layout Demo'),
Of course, this app title, which provides the title across the top of the screen, and be removed entirely. Simply go into the build method, and where you see appBar as show below, delete all of that section.
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
If you delete it, you will not have any of that content, not the blue bar (by default) or the text within it. This is helpful as we’re going to create our own section.
The Main Body
Now we want to modify the body. In the sample at on line 77 where you see body: Center(
This is where we will start.
We need to remove everything after the colon, that is contained within Center, and the Center as well. The last line should be ), // Center
that needs to be removed, but keep the ,
.
The Body needs a widget, so we’re going to add one. First by defining a widget object, and then inserting it where the Center info used to be. We’re going to create an object with this Widget info, and since it is part of the Build process, we’re going to build it here.
Widget titleSection = Container(
padding: const EdgeInsets.all(32),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: const EdgeInsets.only(bottom: 8),
child: const Text(
'Sample Headline',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
),
),
),
Text(
'Subheader',
style: TextStyle(
color: Colors.grey[500],
),
),
],
),
),
/*3*/
Icon(
Icons.star,
color: Colors.red[500],
),
const Text('41'),
],
),
);
If you go through this code, you can see that it is a Container Widget. First it puts a padding all the way around this Widget.
Then Widgets can have children, which it has two of, an Expanded Widget, and an Icon.
The Expanded Widget will take up all remaining horizontal space available to it. It can then have children of it’s own, which you see with the two text boxes.
Notice, to modify more elements, you might need to put your text into a further container widget.
To add this to the body, we’re going to define the body as a Column, which has a list of children. This way we can add different sections.
body: Column(
children: [
titleSection,
],
)
Notice that you can leave an extra comma after the widget object you pass in. This way you can more easily add it.
Now you might ask, why not just put all of the widget info within the body section, like the demo app does. Well, this helps group/isolate our code, so it is easier to read and update if were were necessary.
Building a Button Builder
The next piece of code, is code that we’re going to use to build several buttons. That is because we’re going to use the same layout/style for the buttons.
This code should go after @override Widget build(BuildContext context) { /*...*/ }
Which will also be right before the closing }
for the whole app.
Column _buildButtonColumn(Color color, IconData icon, String label) {
return Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(icon, color: color),
Container(
margin: const EdgeInsets.only(top: 8),
child: Text(
label,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: color,
),
),
),
],
);
}
This function is going to add a button right where it is called. In our case, to the column.
Next we need to add buttons with that code which was just added. Because we need access to context, we have to be careful with where we put this. Specifically it needs to be inside of the build() method, and before the return statement so the code can be reached. I put it up first right after the method header.
Notice how we also create a Color object to pass into our _buildButtonColumn method. We could have written it out, but this makes the code a little cleaner to read, and faster to write. Plus, if we want to change the color, we only have to do it in one location.
Color color = Theme.of(context).primaryColor;
Widget buttonSection = Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
_buildButtonColumn(color, Icons.call, 'CALL'),
_buildButtonColumn(color, Icons.near_me, 'ROUTE'),
_buildButtonColumn(color, Icons.share, 'SHARE'),
],
);
By creating an object, we can then call that object to insert into the children for the body, right below the titleSection. That code should look like:
body: Column(
children: [
titleSection,
buttonSection,
], /* ... */)
Main Text Section
Next we need to create a section of text. We’re going to put this inside of a Padding Widget so we can have some control of layout and sizing. In our example, we will put this right under the buttonSection within the build method.
Widget textSection = const Padding(
padding: EdgeInsets.all(32),
child: Text(
'Lorem ipsum ab facere orci quia deleniti lorem nobis modi lobortis',
'est debitis libero eaque vero. Imperdiet quas officia in eos accusamus',
'erat doloremque harum lacus fugit faucibus inventore voluptates',
'reprehenderit amet illum. Eget metus at excepturi duis mi lacus maxime',
'voluptas fringilla eveniet magnis diam curae nunc? Efficitur leo ante',
'interdum voluptatem risus pulvinar aliquam labore repellendus venenatis',
'aperiam bibendum quisque fugiat temporibus pariatur. Quaerat saepe tortor',
'potenti pellentesque minima consequat ab luctus, ad cumque. Volutpat sint',
'ipsa illum, quisque ullam aliquid. Iusto praesent est qui eros eleifend quibusdam.',
softWrap: true,
),
);
As you look at this section, you can see that a padding surrounds the whole text block, and we have defined a softwrap.
With this object given a variable name, we can add it to the children of the body.
body: Column(
children: [
titleSection,
buttonSection,
textSection,
],
Adding an Image
We’re going to access an image. You can download it here: https://images.unsplash.com/photo-1471115853179-bb1d604434e0?dpr=1&auto=format&fit=crop&w=767&h=583&q=80&cs=tinysrgb&crop=
Now we’re going to have to do several things to add an image, and not all of them deal with source code.
First, we need to have an image. You can use the image above to download. You will need to save this under your project folder, in a new sub-folder called images. You will need to create this sub-folder. I saved this image as lake.jpg
.
Second, since we are loading a static file, we need to let the Flutter config know about it by creating an assets tag. To do this we need to open: pubspec.yam
and edit it.
You need to find the flutter: tag within the yaml file. Now YAML files are case sensitive, and depending upon if you have comments in yours, it could be just a few lines down, or many.
Under flutter:
you will find user-material-design: true
. Under that you may see comments about assets, you will add your asset under those comments. It should look like:
Now that we’ve defined an asset in your pubspec.yam we can reference it in our app. We won’t create an object for it, we’ll just add the following lines to the body, before the titleSection.
Image.asset(
'images/lake.jpg',
width: 600,
height: 240,
fit: BoxFit.cover,
),
BoxFit.cover
tells the framework that the image should be as small as possible but cover its entire render box.
body: Column(
children: [
Image.asset(
'images/lake.jpg',
width: 600,
height: 240,
fit: BoxFit.cover,
),
titleSection,
buttonSection,
textSection,
],
Tip: Adding an asset and inserting it may require a fresh restart. The Hot Reload function did not work for me.
Finally, because you have added more content, you may need to switch the body to not use the column, but use ListView
instead. ListView
will allow for scrolling, which is important when thinking about smaller content items.
Layout Examples in Flutter was originally found on Access 2 Learn
One Comment
Comments are closed.