Everything in Flutter is controlled. This article will explain how to use the basic controls and show you how to combine them with an example.
Grammar can be the basis of knowing the Dart accessibility to read this content, specific introduction can click on Flutter | Dart syntax.
Interface entry
When you create a Flutter app, you can deeply feel that everything is controlled.
The entry to the Flutter App is the main() method in the main.dart file in the lib directory:
void main() {
runApp(MyApp());
}
Copy the code
MyApp is a control:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
appBar: AppBar(title: const Text('Welcome to Flutter')),
body: , // This is where you can populate the controls you want to display)); }}Copy the code
MyApp inherits from StatelessWidget, which is a custom stateless control. To customize a control, override build(), which returns a Widget that is the base class for all controls.
This time it returns the MaterialApp, which is a material Design-compliant control. The Scaffold of the home property type is also a control. The scaffolding that builds the AppBar and body controls is where most of the application’s business interfaces are filled.
It can be seen that the controls in Flutter are directly new, the build layout is declarative, and the layout and logic are mixed together.
The text
Start with the basic text:
Text(
'abc'./ / content
style: TextStyle(
fontSize: 12./ / size
fontWeight: FontWeight.w400, / / word
color: Colors.blue, / color/word
fontFamily: 'pingfang'./ / font
maxLines: 1 // Maximum number of rows));Copy the code
Custom fonts
The code above builds a text control and styles the text. For any custom fonts referenced in this file, you must first store the font file in the app/fonts directory (if not, create a new one) :
Then load the font in the pubspec.yaml file and you can reference it in DART:
Custom colors
In addition to using the system’s predefined colors.xxx Colors, you can also use custom Colors:
Text(
'abc',
style: TextStyle(
color: Color(0xFFB9BEC5), // Custom colors));Copy the code
Construct a Color object directly and pass in the hexadecimal value of the Color.
The rich text
// 'I am a programmer' is split into two paragraphs, with different font size and color
Text.rich(TextSpan(children: [
TextSpan(
text: 'I am',
style: TextStyle(
fontSize: 10,
color: Colors.blue
)
),
TextSpan(
text: 'Programmer',
style: TextStyle(
color: Colors.red,
fontSize: 12))))Copy the code
Text.rich() is a named constructor for the Text control that passes in a TextSpan object with a children property, which means that several TextSpan objects can be passed in, each of which can set the Text property independently. Decompose into several TextSpan objects to achieve the rich text effect.
The picture
Loading local images
Image.asset(
'images/hot_week.webp'.// Local image name
),
Copy the code
The code above builds oneImage
Control is used to display local images, where the image resource images/hot_week.webp must be stored firstapp/images
Directory (if not created) :
Then load the image in the pubspec.yaml file and you can reference it in dart:
Loading network images
Image.network(
circle?.url ?? "",
fit: BoxFit.cover,
)
Copy the code
The Image control has a convenient naming method, network(), which can load images asynchronously just by passing in the Image URL.
The fit property indicates how the image should fit the size of the control. Boxfit. cover scales the image to equal proportions until the control is full of width and height.
Control the size
The size of a Flutter control is not determined by itself, but by its parent control.
This is a proverb that must be kept in mind when arranging Flutter.
So if you want to show a 200 by 200 image, you can only say:
Container(
width: 200,
height: 200,
child: Image.asset('images/hot_week.webp'))Copy the code
Right! Fill the Container with a layer and specify the width and height of the Container.
Try inheriting the above code from the MaterialApp:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: Container(
width: 200,
height: 200,
child: Image.asset('images/hot_week.webp'))); }}Copy the code
When you run the code, you’ll be surprised to see images fill the entire screen. The proverb took effect. Unfortunately, the parent control, the MaterialApp control, has constraints on the child. It requires that the child control cover the entire parent control, so the specified width and height of the Container will not take effect.
Another way to write it is:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(primarySwatch: Colors.blue),
home: Scaffold(
appBar: AppBar(title: const Text('Welcome to Flutter')),
body: Container(
width: 200,
height: 200, color: Colors.red ), ), ); }}Copy the code
This time the 200 * 200 image becomes the Scaffold child and the result is as expected. That’s because scaffolds constrain children to be as big as they want but not bigger than me.
This leads to the second saying about the Flutter layout:
The parent control always imposes a constraint on the child that determines the range and relative position of the child’s width and height.
Margin background rounded corner
The Container control can specify dimensions, interior and exterior margins, background color, and rounded corners.
Container(
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(8)), / / the rounded
color:Colors.red / / fill color
),
padding: EdgeInsets.fromLTRB(10.5.10.5),// Inner margin, specify upper left and lower right respectively
margin: EdgeInsets.all(20),// The margin is 20
child: Text("This is a text with rounded corners."),Copy the code
The above code is shown below:
The idea of “wrapping a parent control to determine the margin, background, and rounded corners” is not quite the same as building Android’s native interface. In the native world these are properties of the control itself. One of the obvious benefits of this approach is decoupling: margins, backgrounds, and rounded corners can be easily attached to any control, rather than having to worry about margins, backgrounds, and rounded corners for each custom control.
Linear container
A Flutter has two linear containers that do not roll: a horizontal Row and a vertical Column.
Row(
children: [
Text('look at here--'),
Text('123--'),
Text('and--'),
Text('more--'),
Text('gift--'),,)Copy the code
The above code looks like this:
The blue lines in the image above represent the boundaries of the Flutter control, which is the interface debugging tool that comes with Flutter. This should only be set in the main() methoddebugPaintSizeEnabled
Set this to true, then run the app again (hot restart does not work) :
void main() {
debugPaintSizeEnabled = true;
runApp(MyApp());
}
Copy the code
As you can see, Column’s parent controls require it to span the screen horizontally, while Column has no constraints on its children, who can determine their own size.
Instead of a vertical container, it is written similarly:
Column(
children: [
Text('look at here--'),
Text('123--'),
Text('and--'),
Text('more--'),
Text('gift--'),,)Copy the code
The above code looks like this:
Similarly, Column is required to cover the entire screen vertically by the parent control, but there is no constraint on the size of the child control.
Expanded
If a child control of a linear container wants to fill up the rest of the container, it can be written like this:
Row(
children: [
Expanded(child: Text('look at here--')),// Fill the remaining space of the container
Text('123--'),
Text('and--'),
Text('more--'),
Text('gift--'),,)Copy the code
The above code has the following effect:
If each child of a linear container is Expanded wrapped, it can passflex
Attributes to determine their proportions:
Row(
children: [
Expanded(child: Text('look at here--'), flex: 2),
Expanded( child: Text('123--'), flex: 3, ),
Expanded( child: Text('and--'), flex: 4, ),
Expanded( child: Text('more--'), flex: 1, ),
Expanded( child: Text('gift--'), flex: 2,),,)Copy the code
The above code looks like this:
alignment
The alignment of linear containers is divided into two axes, mainAxisAlignment and crossAxisAlignment.
For horizontal containers, the main axis is horizontal, and the axis that crosses the horizontal is vertical.
For a longitudinal container, the principal axis is vertical and the axis intersecting the vertical is horizontal.
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,// Divide evenly on the main axis
children: [
Text('look at here--'),
Text('123--'),
Text('and--'),
Text('more--'),
Text('gift--'),,)Copy the code
The above code has the following effect:
Because the parent control requires the Column to span the entire screen vertically, dividing the layout evenly across the main axis causes the child controls to be evenly distributed vertically across the screen. The blue border shows that the size of the control itself has not changed, only its position relative to the parent control.
If you want the child control to be left aligned, you can write:
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,// Divide evenly on the main axis
crossAxisAlignment: CrossAxisAlignment.start, // Align left on the cross axis
children: [
Text('look at here--'),
Text('123--'),
Text('and--'),
Text('more--'),
Text('gift--'),,)Copy the code
The above code looks like this:
The overflow
Column and Row are non-scrollable controls, so if there are too many child controls on the main axis, they will not be fully displayed. This is called overflow:
Row(
children: [
Text('look at here--'),
Text('123--'),
Text('and--'),
Text('more--'),
Text('gift--'),
Text('gift--'),
Text('gift--'),
Text('gift--'),
Text('gift--'),
Text('gift--'),
Text('gift--'),,)Copy the code
Deliberately added several controls to overflow in the horizontal direction:
A yellow and black warning is displayed when an overflow occurs. 4) RenderFlex overlearning by 28 Pixels on the right
Here’s another example of an error:
Row(
children: [
Text('look at here--'),
Text('123--'),
Text('and--'),
Text('more--'),
Text('gift--'),
ListView(scrollDirection: Axis.horizontal),// Horizontal list],)Copy the code
A horizontal list was added to the horizontal container. The Horizontal viewport was given unbounded width. The Horizontal viewport had no constraint on the Horizontal dimension.
Because Column does not constrain its child controls to grow horizontally and vertically, one of the children, incidentally, is the ListView, which is also a free-growing control that grows horizontally. When two controls grow freely in the same direction, the parent control does not know how big it should be.
The solutions are as follows:
Container(
color: Colors.red,
child: Row(
children: [
Text('look at here--'),
Text('123--'),
Text('and--'),
Text('more--'),
Text('gift--'),
ListView(
scrollDirection: Axis.horizontal,
shrinkWrap: true[], (), (Copy the code
ShrinkWrap adds a property to shrinkWrap the Size of the ListView as small as possible to wrap the child controls. This determines the size of the ListView and thus the size of the Column.
To see the Row boundary clearly, wrap it in a Container and add a red background. Run:
There is no error, but the effect is not quite consistent with expectations. The parent container used to fill the screen horizontally with rows, but now it fills the screen vertically with ListView.
This is because the ListView has no restrictions on the height of the child control and its own height is the maximum height of the child control, as is the case with Row. In this case, as long as the ListView child control is high enough, it is possible for the Row to go beyond the bottom of the screen, but why is there no overflow warning? The parent container’s constraint on a Row is that it “spans the screen horizontally, as high as you want, but not higher than me.”
Now comes the third proverb of the Flutter layout:
Although the size and position of the child control are constrained by the parent control, the size of the child control can sometimes affect the size of the parent control.
The integrated use of
Consider an example of a combination: the navigation bar
The navigation bar contains three horizontal buttons, each of which is a vertical combination of Image and Text. So the navigation Column should be a Row containing three columns. Let’s look at each Column:
Column(
mainAxisSize: MainAxisSize.min, // Limit the column height so that it is always minimized and just wraps the child controls
mainAxisAlignment: MainAxisAlignment.center, // The child controls are centered
children: [
Image.asset('images/call.webp'), / / icon
Container( // Container (to increase icon and text spacing)
margin: EdgeInsets.only(top: 8), / / spacing
child: Text( / / text
"CALL",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.blue,
),
),
),
],
)
Copy the code
The above code looks like this:
Then embed the three columns into the Row
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Welcome to Flutter',
home: Scaffold(
appBar: AppBar(
title: const Text('Welcome to Flutter'),
),
body: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
/ / phone
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('images/call.webp'),
Container(
margin: EdgeInsets.only(top: 8),
child: Text(
"CALL",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.blue,
),
),
),
],
),
/ / routing
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('images/route.webp'),
Container(
margin: EdgeInsets.only(top: 8),
child: Text(
"ROUTE",
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.w400,
color: Colors.blue,
),
),
),
],
),
/ / share
Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset('images/share.webp'),
Container(
margin: EdgeInsets.only(top: 8),
child: Text(
"SHARE",
style: TextStyle(
fontSize: 12, fontWeight: FontWeight.w400, color: Colors.blue, ), ), ), ], ) ], ), ), ); }}Copy the code
trailer
The widgets in Flutter are called widgets. They can be divided into stateful widgets and StatelessWidgets. Stateful means a control whose content changes. Stateless means a control that is statically immutable.
The next article will customize a stateful and stateless control, respectively, to better understand the differences as you customize them.
reference
List of all Flutter controls
Layouts in Flutter | Flutter