directory

I will write a column on The nuggets about the basic process of Flutter mastery from the beginning to the relatively proficient. I will update my blog 1-2 times a week!

  • Flutter- Why do so many companies love Flutter

  • Learn about Flutter — Dart knowledge in 5 minutes

  • Learn about the Flutter project from here

  • Flutter started writing projects here

  • This makes it much easier to see the Flutter foundation and layout

  • How is rolling implemented in the Flutter project?

preface

Since our last blog Flutter started writing about this project, we have been familiar with the simple use of statelessWidgets and StatefulWidgets in our projects, and talked about the life cycle of both at the end of the project!

In line with the nature of everything that is a Widget in the world of Flutter, this blog will continue to talk about the basic and layout widgets of Flutter.

  • Flutter Basic Widgets [text, buttons, images, forms]
  • Flutter layout Widget

I hope that you can follow this guide. After one or two months of understanding Flutter knowledge, you will surely have the development level of Flutter! I will continue to provide quality content blog to you, the content currently covers objective-C, Swift, Flutter, small program development. Welcome to like blog and follow me, common progress ~~~

Flutter based Widget

2.1 the text Widget

On Android, you use TextView; IOS uses UILabel to display text; Flutter uses the Text component to control how the Text is displayed.

2.1.1 Ordinary text display

In Flutter, the control display of text can be divided into two categories:

  • Parameters that control text layout, such as textAlign, textDirection, maxLines, overflow, and so on, are all arguments in constructors;

  • Parameters that control text styles, such as font name fontFamily, fontSize fontSize, text color color, text shadow, and so on, are encapsulated in the constructor’s style parameter.

Here are some simple uses of plain text [can directly assign paste]

import 'package:flutter/material.dart'; main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( home: ZXYHomePage(), ); } } class ZXYHomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text("Flutter base Widget"),), body: ZXYHomeContent(),); }} class ZXYHomeContent extends StatelessWidget {@override Widget build(BuildContext context) {return Text(" BuildContext ") \n[Tang] Li Bai song Bai Emperor clouds, thousands of miles jiangling day also. \n The monkeys on both sides of the river cry no longer, the light boat has crossed the mountain ", style: TextStyle(fontSize: 20, color: color.purple,); }}Copy the code

The running results are as follows:

You can change the layout of a Text with a few properties:

  • TextAlign: Text alignment, such as textalign.center

  • MaxLines: Maximum number of display lines, such as 1

  • Overflow: The display of an overflow part, such as textoverflow.ellipsis

  • TextScaleFactor: Controls text scaling, such as 1.24

Only write the modified code, the common code is the above several.

Class ZXYHomeContent extends StatelessWidget {@override Widget build(BuildContext context) {return Text(" BuildContext \n] Li Bai \ N Dynasty ci Bai Emperor clouds, thousands of miles jiangling day also. \n The sound of apes on both sides does not stop, the light boat has passed over ten thousand mountains ", TextStyle( fontSize: 20, color: Colors.purple, ), ); }}Copy the code

MaxLines = 3, maxLines = 4, maxLines = 4, maxLines = 3

2.1.2 Rich text display

The text shown above has the same style applied. What if you want to give them different styles?

  • For Early White Emperor CITY, I wanted the font to be bigger, black, and bold.

  • For example, Li Bai wants red font;

If you want to show this mixed style, you can do it using sharding (SpannableString on Android, NSAttributedString on iOS).

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Text.rich( FontSize: 25, fontWeight: fontWeight. Bold, color: Colors. Black), TextSpan(text: "\n[t] lI Bai ", style: TextStyle(fontSize: 18, color: Colors. RedAccent), TextSpan(text: "\n Worship bai Di clouds, thousands of miles jiangling a day back. \n On both sides of the ape crowed, the light boat has passed the mountain. ")])); }}Copy the code

The result is as follows

2.2 the button Widget

2.2.1 Basis of buttons

The Material Widget library provides a variety of button widgets such as FloatingActionButton, RaisedButton, FlatButton, OutlineButton, and more

  • FloatingActionButton: Float button

  • RaisedButton: The button in Material Design, a raised rectangular Material button

  • FlatButton: Button in Material Design, a shade-free Material Design button

  • OutlineButton: Crossover between button, RaisedButton and FlatButton in Material Design: A button with a border with a transparent background that increases in height and becomes opaque when the button is pressed.

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: <Widget>[ FloatingActionButton( child: Text("FloatingActionButton"), onPressed: () { print("FloatingActionButton Click"); }, ), RaisedButton( child: Text("RaisedButton"), onPressed: () { print("RaisedButton Click"); }, ), FlatButton( child: Text("FlatButton"), onPressed: () { print("FlatButton Click"); }, ), OutlineButton( child: Text("OutlineButton"), onPressed: () { print("OutlineButton Click"); }, ) ], ); }}Copy the code

The running results are as follows:

2.2.2 Custom Styles

The previous buttons use the default style, and we can change the style of the button through some properties

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Column( children: <Widget>[RaisedButton(child: Text(" agreement ", style: TextStyle(color: color.white)), color: Colors.orange, highlightColor: Colors.orange[700], shape: RoundedRectangleBorder(borderRadius: BorderRadius. Circular (20)), onPressed: () {print (" agreement ");},),,); }}Copy the code

The running results are as follows:

2.3 the picture Widget

Images can make our application more colorful. Flutter uses the Image component.

There are many constructors for the Image component. Here we will learn two:

  • Image.assets: loads images of local resources.

  • Image.network: Loads images from the network;

2.3.1 Loading Network Images

Loading web images into Flutter is relatively easy. Passing in urls directly requires no configuration, so let’s see how to load web images into Flutter first.

Let’s look at the properties of the Image that can be set:

const Image({ ... This.width, // the width of the picture this.height, // the height of the picture this.color, // the blending value of the picture this.colorblendMode, // Align this. Repeat = ImageRepeat. NoRepeat,// Align this. })Copy the code
  • Width, height: Used to set the width and height of the image. If the width and height are not specified, the image will display its original size according to the current parent container limit. If only one of the width and height properties is set, the other property will be scaled by default, but you can use the fit property described below to specify the adaptation rules.

  • Fit: This property is used to specify the image’s fit mode when the image’s display space and image size are different. The fit mode is defined in BoxFit, which is an enumerated type with the following values:

  • Fill: it will stretch to fill the display space, the aspect ratio of the picture itself will change, and the picture will be deformed.

  • Cover: the image will be enlarged according to the aspect ratio of the image and then centered to fill the display space. The image will not be deformed, and the part beyond the display space will be clipped.

  • Contain: This is the default image adaptation rule, the image will ensure that the image itself length to width ratio unchanged under the condition of scaling to adapt to the current display space, the image will not be distorted.

  • FitWidth: The width of the image will be scaled to the width of the display space, the height will be scaled to scale, and then the image will be centered. The image will not be distorted, and the parts that exceed the display space will be clipped.

  • FitHeight: The height of the image will be scaled to the height of the display space, the width will be scaled to scale, and then the center display, the image will not be distorted, the part of the display space will be cropped.

  • None: The image has no adaptive policy and will be displayed in the display space. If the image is larger than the display space, only the middle part of the image will be displayed in the display space.

  • Color and colorBlendMode: you can mix colors for each pixel when drawing the picture. Color specifies the blend color and colorBlendMode specifies the blend mode.

  • Repeat: Specifies a repeat rule for the image when the image itself is smaller than the display space.

Let’s do a walkthrough on some of these properties:

Notice that we’re using a Container, you can think of it as a UIView or a View, which is a Container; I’ll focus on the use of this component later;

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Container( child: Image.network( "https://pics0.baidu.com/feed/e1fe9925bc315c606acd1d9c18dcae15485477d8.jpeg?token=2a07fddc2d1d3fd8b357dddb28eeb6c9", alignment: Alignment.topCenter, repeat: ImageRepeat.repeatY, // color: Colors.red, colorBlendMode: BlendMode.colorDodge, ), width: 300, height: 300, // color: Colors.yellow, ), ); }}Copy the code

The running results are as follows:

2.3.2 Loading a Local Image

Loading local image is a bit more troublesome, you need to import the image, and configure: [2x, 3X these configuration network has a lot of explanation, this blog is not mainly this, refer to the following can also be implemented]

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Container( width: 300, height: 300, // color: Colors.yellow, child: Image.asset("assets/images/home/home.png"), ), ); }}Copy the code

The running results are as follows:

2.3.3 Realize rounded corner image

Method 1: CircleAvatar

CircleAvatar can be implemented as a rounded avatar and can also be added as a child Widget:

Const CircleAvatar({Key Key, this.child, // child Widget this.backgroundColor, // backgroundColor this.backgroundImage, ForegroundColor, // foregroundColor this.radius, // radius this.minradius, // minimum radius this.maxradius, // maximum radius})Copy the code

To implement a circular head:

  • Note 1: NetworkImage is used here, because backgroundImage requires that we pass in an ImageProvider;

  • ImageProvider is an abstract class. In fact, all previously created Image objects contain an Image property, which is an ImageProvider

  • Note 2: There is also a text inside, but a Container is wrapped around the text.

  • The Container is used to control the position of text in the Container.

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: CircleAvatar( radius: 100, backgroundImage: NetworkImage("https://gimg2.baidu.com/image_search/src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180809%2F7 38 ee6c928994eab813bcd1cff90c361.jpeg&refer=http%3a%2f%2f5b0988e595225.cdn.sohucs.com & app = 2002 & size = f9999, 10000 & q = a80 & n = 0 &g=0n&fmt=jpeg?sec=1611813085&t=ee9e2201ec99388af35fb2c8fd0b9f12"), child: Container( alignment: Alignment(0,.5), width: 200, height: 200, child: Text(" }}Copy the code

The running results are as follows:

Method 2: ClipOval

ClipOval can also implement rounded avatars, and is usually used with only avatars

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: ClipOval( child: Image.network( "https://gimg2.baidu.com/image_search/src=http%3A%2F%2F5b0988e595225.cdn.sohucs.com%2Fimages%2F20180809%2F738ee6c928994e Ab813bcd1cff90c361.jpeg&refer=http%3A%2F%2F5b0988e595225.cdn.sohucs.com & app = 2002 & size = f9999, 10000 & q = a80 & n = 0 & g = 0 n & FMT =, jpe. g?sec=1611813085&t=ee9e2201ec99388af35fb2c8fd0b9f12", width: 200, height: 200, ), ), ); }}Copy the code

** Method 3: **Container+BoxDecoration

And this is the way we’re going to do it when we talk about containers.

2.4 the form widgets

One way to interact with the user is through input fields, such as register, log in, and search, which collect user input and submit it to the server.

2.4.1 Use of TextField

The introduction of TextField

TextField is used to receive text input from the user. It provides a large number of attributes, but there is no need to learn them individually

const TextField({ Key key, this.controller, this.focusNode, this.decoration = const InputDecoration(), TextInputType keyboardType, this.textInputAction, this.textCapitalization = TextCapitalization.none, this.style, this.strutStyle, this.textAlign = TextAlign.start, this.textAlignVertical, this.textDirection, this.readOnly = false, ToolbarOptions toolbarOptions, this.showCursor, this.autofocus = false, this.obscureText = false, this.autocorrect = true, this.maxLines = 1, this.minLines, this.expands = false, this.maxLength, this.maxLengthEnforced = true, this.onChanged, this.onEditingComplete, this.onSubmitted, this.inputFormatters, This.enabled, this.cursorWidth = 2.0, this.cursorradius, this.cursorcolor, this.keyboardappearance, This. ScrollPadding = const edgeinsets.all (20.0), this. DragStartBehavior = DragStartBehavior.start, this.enableInteractiveSelection = true, this.onTap, this.buildCounter, this.scrollController, this.scrollPhysics, })Copy the code

To learn about some of the more common attributes:

  • Some properties are simple: keyboardType Specifies the type of the keyboard, style sets the style, textAlign text alignment, maxLength specifies the maximum number of lines to display, etc.

  • Decoration: Sets the style associated with the input box

  • Icon: Sets the icon displayed on the left

  • LabelText: Displays a prompt text above the input box

  • HintText: placeholder text to display the prompt

  • Border: The border of the input box. By default, there is a border at the bottom, which can be removed by InputBorder. None

  • Filled: Whether to fill the input box. The default value is false

  • FillColor: indicates the filling color of the input box

  • Controller:

  • OnChanged: Listens for changes to the content of the input box, passing a callback function

  • OnSubmitted: A function that is called back when you click down in the bottom right corner of the keyboard

TextField style and listener

To illustrate the TextField decoration property and listener:

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Container( padding:  EdgeInsets.all(20), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextFieldDemo() ], ), ); } } class TextFieldDemo extends StatefulWidget { @override _TextFieldDemoState createState() => _TextFieldDemoState(); } class _TextFieldDemoState extends State<TextFieldDemo> { @override Widget build(BuildContext context) { return TextField(decoration: InputDecoration(icon: icon (Icons. People), labelText: "username", hintText: "please enter username", border: InputBorder.none, filled: true, fillColor: Colors.lightGreen ), onChanged: (value) { print("onChanged:$value"); }, onSubmitted: (value) { print("onSubmitted:$value"); }); }}Copy the code

Running results:

When YOU click username

You can add a Controller to the TextField, which you can use to set the initial value of the text or to listen for changes to the text. In fact, Flutter creates a TextEditingController by default if we do not provide a Controller for TextField. This conclusion can be obtained by reading the source code:

@override void initState() { super.initState(); / /... If (widget.controller == null) _controller = TextEditingController(); }Copy the code

You can also create a Controller to control something:

class _TextFieldDemoState extends State<TextFieldDemo> { final textEditingController = TextEditingController(); @override void initState() { super.initState(); / / 1. Set the default textEditingController. Text = "Hello World"; / / 2. Listening text box textEditingController. AddListener (() {print (" textEditingController: ${textEditingController. Text} "); }); } / /... Omit build method}Copy the code

2.4.2 Use of Form

When developing registration and login pages, there are often multiple forms that need to fetch content or perform some validation at the same time. It would be troublesome to validate each TextField separately. The idea behind Flutter is that you can put multiple input tags into a form. The idea behind Flutter is that you can use forms to group input fields and perform operations in one place.

The Form Form is also a Widget where we can put our input field.

But the input field in the Form Form must be of type FormField

  • TextField is derived from StatefulWidget and is not a FormField type.

  • You can use TextFormField, which is similar to TextField and inherits from FormField;

Implement a registered page by wrapping the Form: the code is as follows

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Container( padding:  EdgeInsets.all(20), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ ZXYFormDemo() ], ), ); } } class ZXYFormDemo extends StatefulWidget { @override _ZXYFormDemoState createState() => _ZXYFormDemoState(); } class _ZXYFormDemoState extends State<ZXYFormDemo> { @override Widget build(BuildContext context) { return Form( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextFormField( decoration: InputDecoration(icon: icon (Icons. People), labelText: "Icons"),), TextFormField(obscureText: true, decoration: obscureText: InputDecoration(icon: icon (Icons. Lock), labelText: "password"),), SizedBox(height: 16,), Container(width: Double. Infinity, height: 44, child: RaisedButton(color: Colors. LightGreen, child: Text("注 册", style: TextStyle(fontSize: 20, color: color.white),), onPressed: () {print(" pressed ");},),),); }}Copy the code

Running results:

Save and get form data

After you have a form, you need to click register, and you can get and save the data in the form at the same time. How can you do that?

  • 1. Listen for the register button click in the onPressed callback that was already listened on. (Of course, if there is too much nesting, you can extract it into a separate method later)

  • 2. When the button is clicked, obtain the form information of user name and password.

How do I get form information for both username and password?

  • If the callForm's State objectThe save method calls the onSave callback to the TextFormField put in the Form:

The code is as follows:

TextFormField(decoration: InputDecoration(icon: icon (Icons. People), labelText: "user name or phone number"), onSaved: (value) {print(" username: $value"); },),Copy the code
  • But is there any way we can get it when we click the buttonThe Form objectTo call its save method?

How can a Flutter get a State object that gets a StatefulWidget by reference? ** Answer: Bind a GlobalKey.

The case code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Container( padding:  EdgeInsets.all(20), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ ZXYFormDemo() ], ), ); } } class ZXYFormDemo extends StatefulWidget { @override _ZXYFormDemoState createState() => _ZXYFormDemoState(); } class _ZXYFormDemoState extends State<ZXYFormDemo> { final registerFormKey = GlobalKey<FormState>(); String username, password; void registerForm() { registerFormKey.currentState.save(); print("username:$username password:$password"); } @override Widget build(BuildContext context) { return Form( key: registerFormKey, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ TextFormField( decoration: InputDecoration( icon: Icon(Icons. People), labelText: "username or phone number"), onSaved: (value) {this.username = value;},), TextFormField(obscureText: True, decoration: InputDecoration(icon: icon (Icons. Lock), labelText: "password"), onSaved: (value) { this.password = value; }, ), SizedBox(height: 16,), Container( width: double.infinity, height: 44, child: RaisedButton(color: Colors. LightGreen, child: Text(" ", style: TextStyle(fontSize: 20, color: Colors.white),), onPressed: registerForm, ), ) ], ), ); }}Copy the code

Run result: — done

Flutter layout Widget

In order to achieve the various layouts of the components in the Flutter interface, layouts are required. Unlike other terminals, Flutter layouts are also performed using widgets because everything in Flutter is widgets. There are many layout components in Flutter. There are 31 components for Flutter layout [1]. In the process of learning, it is not necessary to master all of them, master the most commonly used, some special components when used to check the documents; Flutter divides layout components into single-child layout widgets and multi-child layout widgets.

3.1 Monad layout components

A monad layout component has only one child component. You can set the location of the child component by setting some properties. Common monadic layout components are Align, Center, Padding, and Container.

3.1.1 the Align components

Introduce the Align

If you look at the word Align, it has something to do with alignment. Align is usually just a property in other applications (iOS, Android, front-end), but Align is also a component in Flutter.

Align = Align Align = Align Align = Align Align = Align Align

const Align({ Key key, this.alignment: This. widthFactor, // widthFactor will be as large as possible if not set this.heightFactor, // heightFactor, if not set, As large as possible child // Child Widget to be laid out})Copy the code

WidthFactor and heightFactor in particular are explained here:

  • Because the alignment of child components within parent components must be based on the fact that the parent component knows its own scope (width and height);

  • If widthFactor and heightFactor are not set, the default Align is as large as possible (occupying as much of its parent component as possible);

  • They can also be set, such that widthFactor is set to 3, so that the width relative to Align is three times the span of the child component;

* * * * Center component

Center is introduced

In fact, the Center component inherits from Align, except that alignment is set to align.center. Source code analysis:

class Center extends Align {
  const Center({
    Key key,
    double widthFactor,
    double heightFactor,
    Widget child
  }) : super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
}
Copy the code

Center drill

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Align( child: Icon(Icons.pets, size: 36, color: Colors.red), alignment: Alignment.bottomRight, widthFactor: 3, heightFactor: 3, ); }}Copy the code

Padding components

The Padding is introduced

The Padding component is also a property on the other end, but is a Widget in a Flutter, but there is no Margin Widget in a Flutter, because Padding can also be done using Padding. Padding is usually used to set the margin between the child Widget and the parent Widget (you can call it the inside margin of the parent component or the margin of the child Widget).

Source code analysis:

Const Padding({Key Key, @required this. Padding, // EdgeInsetsGeometry type (Abstract class), using EdgeInsets Widget child,})Copy the code

Padding drill

Code walkthroughs:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( padding: EdgeInsets. All (20), child: Text(" EdgeInsets. Bamboo stick grain in ear shoes light horse, who is afraid? A rush of rain any life." , style: TextStyle( color: Colors.redAccent, fontSize: 18 ), ), ); }}Copy the code

The running results are as follows:

3.1.2 Container components

The Container component is similar to other Android views and iOS UIViews. If you need a view that has a background color, an image, a fixed size, needs a border, rounded corners, etc., then you can use the Container component.

The Container is introduced

Containers are used very often in development, especially as Container components. Let’s take a look at the attributes of a Container:

Container({this.alignment, this.padding, // Color, Color, Color, Color, Color, Color, Color, Color, Color, Color, Color, Color // Double width,// double height of the container,// BoxConstraints constraints, // this. Margin,// This.transform, // transform this.child,})Copy the code

Most of these properties have already been covered in other containers, but there are two things to note:

  • The container size can be specified through the width and height attributes, or through constraints. If both exist, width and height take precedence. Inside the Container, it actually generates a constraints based on width and height.

  • Color and decoration are mutually exclusive. In fact, when color is specified, a decoration is automatically created in the Container.

  • Properties of decoration will be studied in detail later.

The Container drill

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Container( color: Color.fromRGBO(3, 3, 255, .5), width: 100, height: 100, child: Icon(Icons.pets, size: 32, color: Colors.white), ), ); }}Copy the code

BoxDecoration

Container has an important property, decoration:

  • The corresponding type is Decoration, but it is an abstract class.

  • Its implementation class BoxDecoration is often instantiated during development.

BoxDecoration

Const BoxDecoration({this.color, // color, will conflict with the color attribute in the Container this.image, // background image this.border, // border, Inside each frame using BorderSide enclosing borderRadius, / / the rounded effect enclosing boxShadow, / / shadow effect this. Gradient, this. / / a gradient effect backgroundBlendMode, Rectangle = BoxShape. Rectangle, rectangle, rectangle, rectangle})Copy the code

Part of the effect demonstration:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Container( // color: Color.fromRGBO(3, 3, 255, .5), width: 150, height: 150, child: Icon(Icons.pets, size: 32, color: Color: color.white), decoration: BoxDecoration(color: color.amber, // background color: border. RedAccent, width: 3, style: borderstyle.solid), // you can also use Border. Colors.redAccent, // width: 3, // style: BorderStyle.solid // ), borderRadius: BorderRadius. Circular (20), // Only sets boxShadow: [boxShadow (offset: offset (5, 5), color: Colors. Purple, blurRadius: 5)], // Shape: boxShape. circle, // Will conflict with borderRadius [ Colors.green, Colors.red ] ) ), ), ); }}Copy the code

The running results are as follows:

Implement rounded corner image

The Container+BoxDecoration can be used to create rounded images.

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Center( child: Container( width: 200, height: 200, decoration: BoxDecoration( borderRadius: BorderRadius.circular(20), image: DecorationImage( image: NetworkImage("https://tva1.sinaimg.cn/large/006y8mN6gy1g7aa03bmfpj3069069mx8.jpg"), ) ), ), ); }}Copy the code

The running results are as follows:

3.2 Multiple sub-layout components

In development, you often need to place multiple widgets together for layout, such as horizontal, vertical, or even overlapping, such as placing text on top of an image. You need to use multi-child Layout widgets at this point. Row, Column, and Stack are common layout components. Learn how to use them.

3.2.1 Flex components

In fact, the Row and Column components you learned inherit from the Flex components.

  • The main difference between Flex components and Row and Column attributes is the extra direction.

  • Row when direction is Axis. Horizontal.

  • When the direction value is Axis. Vertical, Column.

The Row components

The Row component is used to line up all the child widgets in a way that should be borrowed from the Flex layout of the Web. If you are familiar with the Flex layout, you will find it very simple.

View the Row properties from the source:

Row({ Key key, MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start, MainAxisSize MainAxisSize = mainAxissize.max, / / horizontal direction as large as possible CrossAxisAlignment CrossAxisAlignment = CrossAxisAlignment. Center, / / intersections alignment TextDirection TextDirection, // Horizontal layout order of the child widgets (default is the text direction of the current Locale (for example, left to right for Chinese and English, In Arabic, it goes from right to left.) TextBaseline TextBaseline, TextBaseline List<Widget> children = const <Widget>[],})Copy the code

The Row drill

Some of the attributes for a simple code walkthrough, some of the other attributes you learn your own

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.max, children: <Widget>[ Container(color: Colors.red, width: 60, height: 60), Container(color: Colors.blue, width: 80, height: 80), Container(color: Colors.green, width: 70, height: 70), Container(color: Colors.orange, width: 100, height: 100), ], ); }}Copy the code

The running results are as follows:

Expanded

What if you want the red and yellow Container widgets not to have a fixed width, but to occupy the rest?

You can use Expanded to wrap the Container Widget and leave its width unchecked.

The Flex property, the elasticity factor, and the Row determine how much of the remaining space they occupy based on the elasticity factor of the two Expanded

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: <Widget>[ Expanded( flex: 1, child: Container(color: Colors.red, height: 60), ), Container(color: Colors.blue, width: 80, height: 80), Container(color: Colors.green, width: 70, height: 70), Expanded( flex: 1, child: Container(color: Colors.orange, height: 100), ) ], ); }}Copy the code

The result is as follows

3.2.2 Column components

The Column component is used to arrange all the child widgets in a single Column. After learning the previous Row, the Column is just in a different direction from the Row.

The Column is introduced

Looking directly at the source code: we found that the Row property is consistent, and will not explain

 Column({
    Key key,
    MainAxisAlignment mainAxisAlignment = MainAxisAlignment.start,
    MainAxisSize mainAxisSize = MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment = CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection = VerticalDirection.down,
    TextBaseline textBaseline,
    List<Widget> children = const <Widget>[],
  })
Copy the code

The Column drill

Change Row to Column to see how this code works:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, crossAxisAlignment: CrossAxisAlignment.end, mainAxisSize: MainAxisSize.min, children: <Widget>[ Expanded( flex: 1, child: Container(color: Colors.red, width: 60), ), Container(color: Colors.blue, width: 80, height: 80), Container(color: Colors.green, width: 70, height: 70), Expanded( flex: 1, child: Container(color: Colors.orange, width: 100), ) ], ); }}Copy the code

Running results:

3.2.3 Stack components

In development, it is likely that multiple components will need to overlap, such as text on a single image or a button. This can be done using frames in Android, absolute positioning can be used on the Web, and the Stack layout needs to be used in Flutter

The Stack is introduced

Look at the Stack properties from the source code:

Stack({
  Key key,
  this.alignment = AlignmentDirectional.topStart,
  this.textDirection,
  this.fit = StackFit.loose,
  this.overflow = Overflow.clip,
  List<Widget> children = const <Widget>[],
})
Copy the code
  • Alignment: This parameter determines how to position the child widget without positioning (without using the tourists) or partial positioning. **left, right for the horizontal axis, top, bottom for the vertical axis, as long as it contains a positioning attribute on the axis even if there is a positioning on the axis.

  • TextDirection: Like the textDirection function of Row and Wrap, it is used to determine the reference frame of alignment: LTR indicates that the alignment start indicates left and the alignment end indicates right. TextDirection is textdirection. RTL. In this case, start indicates the right and end indicates the left.

  • Fit: This parameter is used to determine how unpositioned child widgets fit into the Stack size. Loose indicates the size to use the child widgets, and stackfit. expand indicates the size to expand into the Stack.

  • Overflow: This property determines how to display child widgets that are out of the Stack display space. With overflow. clip, the excess will be clipped (hidden), but not with overflow. visible.

Stack drill

The code is as follows:

class ZXYHomeContent extends StatelessWidget { @override Widget build(BuildContext context) { return Stack( children: <Widget>[ Container( color: Colors.purple, width: 300, height: 300, ), Positioned( left: 20, top: 20, child: 21. Favorite, size: 50, color: Colors. White), would offer 21 tourists a small glimpse of space. TextStyle(fontSize: 20, color: Colors.white)), ) ], ); }}Copy the code

The running results are as follows:

conclusion

This article introduces Flutter’s basic widgets and layout widgets in detail to familiarize you with the use of widgets in your project. Everything about Flutter is a Widget after reading this article.

From the above, you can write a simple login interface and show the layout of the UI (which widgets to use). You can write the above Demo by hand. We believe that one or two related blog posts per week will deepen your understanding of the Flutter project.

Thank you for your praise and attention to me, common progress, mutual encouragement!!