I will update a series of Flutter text tutorials in the coming days
Update progress: at least two articles per week;
Update location: first in the public account, the next day update in nuggets, Sifu, developer headlines and other places;
More communication: You can add me on wechat at 372623326 and follow me on Weibo at CoderWhy
I hope you can help forward, click to see, give me more creative power.
Create the Flutter project
There are two ways to create a Flutter project: from the command line and through development tools
1.1. Create a vm on the CLI
It is very easy to create from the command line. Enter the following command on the terminal:
- ** Note: the name of the **Flutter should not contain any special characters and should not be marked with a hump
- After creation, use your favorite development tool to open it
flutter create learn_flutter
Copy the code
1.2. Created using development tools
I can also create it directly from Android Studio:
- choose
Start a new Flutter project
, then fill in the relevant information, which will not be repeated here
1.3. Default program analysis
When we create an application and run it on an emulator (I chose iPhone emulator here, Android can also do this), we will see something like this:
Default project analysis:
- We’ve looked at the directory structure before, and there’s one in the directory
lib
Folder, which contains the Flutter code we wrote; - I opened it and found one inside
main.dart
It is what we start the FlutterEntrance to the file
And there areThe main function
;
Default code analysis:
- This is a counter example, click on the lower right corner
+
Symbol, the number shown above is incremented; - But our first look at the code in Main.dart might reveal a lot
Don't know
Do not know how this content is written;
As a beginner, my advice is to delete all the code inside the Flutter and create the code from scratch so that the structure of the Flutter application is clear.
Start Flutter code
2.1. Hello World
2.1.1. Requirements of Hello World
In any development, we start with the ancestral Hello World, so here are our requirements:
- In the center of the screen, a Hello World is displayed.
2.1.2. Implementation of Hello World
Let’s start writing Hello World:
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(Text("Hello World", textDirection: TextDirection.ltr));
}
Copy the code
Of course, we have implemented the above code to display Hello World on the interface:
- but
No center
.The font is also a little small
; - We’ll solve these problems later, first understand the current few lines of code;
Some of the above code is familiar to us, and some is not clear:
- For example, we know the Dart program
The entry is the main function
Dart writes Flutter, so the entry to Flutter is also main. - But we imported
What is Material
? - Also, we call one in the main function
RunApp () function
What is it?
Now, let’s do some analysis of the code we don’t know.
2.2. Code analysis
2.2.1. RunApp and widgets
RunApp is a function provided within a Flutter that is called when we start a Flutter application
- You can view this function by clicking on the runApp source
- We will not analyze the specific source code for the moment (because I find too much theory is not friendly for beginners)
voidrunApp(Widget app) { ... Omit code}Copy the code
This function lets us pass in something: Widget?
Let’s start with Widget translation:
- Widgets have many translations in the country;
- People who have done Android, iOS and other development, like to translate it into controls;
- People who have done Vue, React, etc., like to translate it into components;
- If we use Google, widgets translate to widgets;
- There is no saying which translation is necessarily right or wrong, but I personally prefer widgets or components;
What exactly is a Widget?
- We learn about Flutter from the very beginning with one basic understanding: everything in Flutter is a Widget;
- In our iOS or Android development, we have many types of interfaces: Application, View Controller, Activity, View, Button, etc.
- But in Flutter, these things are just different widgets;
- In our entire application
What you see
Almost all widgets, evenInside margin setting
, we also need to use a name calledThe Padding of the Widget
To do;
The runApp function lets us pass in a Widget:
- But we don’t have widgets right now, so what do we do?
- We can import the Material library that Flutter already provides to us by default to use many of its built-in widgets;
2.2.2. Material design style
What is material?
- Material is a set that Google is pushing
Design style
, orDesign language
,The design specification
And so on; - There are a lot of design specifications, like
color
,Typesetting of text
,Respond to animation with transitions
,fill
And so on; - It’s highly integrated in Flutter
Material style widgets
; - In our application, we can directly use these widgets to create our application (more on that later);
Text widget analysis:
- We can use the Text widget to display the Text;
- We find that the Text Widget inherits from the StatelessWidget, and the StatelessWidget inherits from the Widget;
- So we can pass the Text widget into the runApp function
- There are a lot of attributes, but we’ve learned the Dart syntax, so you’ll notice that only the this.data attribute must be passed in.
class Text extends StatelessWidget {
const Text(
this.data, {
Key key,
this.style,
this.strutStyle,
this.textAlign,
this.textDirection,
this.locale,
this.softWrap,
this.overflow,
this.textScaleFactor,
this.maxLines,
this.semanticsLabel,
this.textWidthBasis,
});
}
Copy the code
StatelessWidget
- StatelessWidget inherits from Widget;
- I’ll explain its use in more detail later;
abstract class StatelessWidget extends Widget {
/ /... Omit code
}
Copy the code
2.3. Code improvement
2.3.1. Improve the interface style
We found that the current code was not the end result we wanted:
- We might want the text to be centered and larger;
- Center display:You need to use another Widget,
Center
; - Larger Text: You need to style the Text;
We modify the code as follows:
- We wrapped a Center widget around the Text widget, with Text as its child;
- Also, we give the Text component a property: style, which corresponds to the TextStyle type;
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(
Center(
child: Text(
"Hello World",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 36),),)); }Copy the code
2.3.2. Improve the interface structure
Currently we can display HelloWorld, but we find that the background at the bottom is black and our page is not structured enough.
- A normal App page should have some structure, like it usually does
The navigation bar
There will be someThe background color
Etc.
In development, we do not need to build such a structured interface from scratch, we can use the Material library, directly use some of the packaged components to complete some of the structure.
We do this with the following code:
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("CODERWHY"),
),
body: Center(
child: Text(
"Hello World",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 36),),),),)); }Copy the code
Wrap a MaterialApp in the outermost layer
- This means that throughout the application we will use something of the MaterialApp style to facilitate our design of the application, and we currently use two of these properties;
- Title: This is the title that will be displayed when opening the multitasking switch window on the Android system. (I don’t have to write it yet.)
- Home: is the page that was displayed when the application started. We passed in a Scaffold.
What is scaffolding?
- The translation is
The scaffold
Scaffolding is the basic structure of the page; - So we passed a Scaffold object to the Home property of the MaterialApp as a Widget to enable display.
- Scaffolding also has some properties such as
appBar
andbody
; - AppBar is for designing the navigation bar, and we passed in one
The title attribute
; - The body is the content part of the page, and we passed in a Text Widget wrapped in the Center that we created earlier.
2.3.3. Advanced case implementation
We can have more elements in the interface:
- As you’ve written this, you’ve probably noticed
Nested too much
Don’t worry, we will refactor the code later
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(
MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("CODERWHY"),
),
body: Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Checkbox(
value: true,
onChanged: (value) => print("Hello World")),
Text(
"Consent agreement",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 20), a)],),),),)); }Copy the code
2.4. Code refactoring
2.4.1. Create your own Widget
Many people who learn about Flutter are discouraged by the nesting of Flutter. When code is nested too much, the structure is easily obscured.
There are two points I would like to make:
- 1. The whole process of Flutter development is to form a tree of widgets, so nesting is normal.
- 2. As for the indent of Flutter code, we use 2 Spaces for more development (2 Spaces are mostly used in front-end development, if you prefer 4, it’s ok)
However, we develop such a simple program with so much nesting, what if the application is more complex?
- We can encapsulate our code, encapsulate it in our own widgets, create our own widgets;
How do you create your own widgets?
- In Flutter development, we can inherit a StatelessWidget or StatefulWidget to create our own Widget class.
- StatelessWidget: A Widget that has no state change and is usually just a display;
- StatefulWidget: A Widget whose state needs to be saved and whose state may change;
In the example above, we used the StatelessWidget to refactor our code, so let’s learn how to use the StatelessWidget to refactor our code.
StatefulWidget we’ll look at in a later case;
2.4.2. StatelessWidget
Statelesswidgets are typically widgets that have no State to maintain:
- Their data is usually written to death (data placed in widgets must be defined as final, why? I’ll cover StatefulWidget in the next section);
- Passed in from the parent Widget and cannot be modified once passed in;
- Get data from the InheritedWidget to use (more on this later);
Let’s look at the format for creating a StatelessWidget:
- 1. Make the Widget you create inherit from the StatelessWidget;
- 2. StatelessWidget contains a method that must be overridden: the build method;
class MyStatelessWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
return< Return our Widget The Widget to render, such as a Text Widget>; }}Copy the code
Build method:
- Flutter executes its build method when it gets the StatelessWidget we created ourselves.
- We need to tell Flutter in the build method what elements our Widget wants to render, such as a Text Widget;
- The StatelessWidget does not actively execute the Build method, which is re-executed when the data we are using changes.
When is the build method executed? :
- 1. When our StatelessWidget is first inserted into the Widget tree (that is, when it is first created);
- When our parent Widget changes, the child Widget is rebuilt.
- 3. If our Widget relies on some InheritedWidget data, when the InheritedWidget data changes;
2.4.3. Reconstruct the case code
Now we can refactor our code using the StatelessWidget
- Because our entire code is just some data presentation, no data changes, just use the StatelessWidget;
- In addition, for better encapsulation, I split the code into two layers to make the code structure look clearer. (The specific splitting method will be continuously reflected in the following cases. At present, we will split two layers first.)
The refactored code looks like this:
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("CODERWHY"),
),
body: HomeContent(),
),
)
}
}
class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Checkbox(
value: true,
onChanged: (value) => print("Hello World")),
Text(
"Consent agreement",
textDirection: TextDirection.ltr,
style: TextStyle(fontSize: 20() [() [(); }}Copy the code
Case study
3.1. Final effect of the case
Let’s take a look at the final presentation of the case:
- For this effect we will use a lot of widgets that we don’t touch;
- It doesn’t matter, I’ll go through the common widgets one by one;
- The main purpose of this case is to familiarize everyone with the development mode of Flutter and the packaging process of custom widgets.
3.2. Custom widgets
In our case, it is clear that a product presentation is a large Widget, which contains the following widgets:
- Title Widget: Done using a Text Widget;
- Described Widget: Done using a Text Widget;
- Image Widget: Done using an Image Widget;
- To align the above three widgets vertically, we can use a Column Widget (we used Row horizontally once in the previous section).
In addition, the titles, descriptions, and images are all different, so we can let the Parent Widget determine the content:
- Create three member variables to hold the data passed in by the parent Widget
class ProductItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
ProductItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
Text(title, style: TextStyle(fontSize: 24)),
Text(desc, style: TextStyle(fontSize: 18)), Image.network(imageURL) ], ); }}Copy the code
3.3. Display of list data
Now we can create three productitems to display:
- MyApp is the same as in the previous chapter, there is no change;
- In HomeContent, we use a Column because the three ProductItem we created are aligned vertically
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.blueAccent
),
home: Scaffold(
appBar: AppBar(
title: Text("CODERWHY"), ), body: HomeContent(), ), ); }}class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
ProductItem("Apple1"."Macbook Product1"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72j6nk1d4j30u00k0n0j.jpg"),
ProductItem("Apple2"."Macbook Product2"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72imm9u5zj30u00k0adf.jpg"),
ProductItem("Apple3"."Macbook Product3"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72imqlouhj30u00k00v0.jpg"),]); }}Copy the code
The running effect is as follows:
- Error message: yellow zebra crossing appears below;
- This is because in the layout of a Flutter, content cannot go beyond the screen. When a Flutter goes beyond the screen, it does not automatically scroll. Instead, the following error is reported.
How can this problem be solved?
- We’ll just change Column to ListView;
- ListView can make its child widgets scroll;
3.4. Adjustment of case details
3.4.1. Overall interface margins
What if we want the entire content to be spaced away from the edge of the screen?
- We need to use another Widget: Padding, which has a Padding property to set the margin size;
- That’s right, setting the inside margin also uses a Widget, which is the Padding;
3.4.2. Inside margins and borders
We now want to add an inner margin and a border to all items. How do we do that?
- You can use the Widget of a Container, which has the padding property inside it, and you can use decoration to set the border.
- Container, we’ll talk about it in more detail later, so let’s use it first;
3.4.3. Spacing of text and pictures
We want to add some space between the image and the text. How do we do that?
- Method 1: Add an upward or downward inner margin to the image or text.
- Method 2: Using the SizedBox Widget, set a height property to increase the distance.
3.5. Final implementation code
Finally, I give the final implementation code:
import 'package:flutter/material.dart';
main(List<String> args) {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(
primaryColor: Colors.blueAccent
),
home: Scaffold(
appBar: AppBar(
title: Text("CODERWHY"), ), body: HomeContent(), ), ); }}class HomeContent extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: ListView(
children: <Widget>[
ProductItem("Apple1"."Macbook Product1"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72j6nk1d4j30u00k0n0j.jpg"),
ProductItem("Apple2"."Macbook Product2"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72imm9u5zj30u00k0adf.jpg"),
ProductItem("Apple3"."Macbook Product3"."https://tva1.sinaimg.cn/large/006y8mN6gy1g72imqlouhj30u00k00v0.jpg"),,),); }}class ProductItem extends StatelessWidget {
final String title;
final String desc;
final String imageURL;
ProductItem(this.title, this.desc, this.imageURL);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
border: Border.all()
),
child: Column(
children: <Widget>[
Text(title, style: TextStyle(fontSize: 24)),
Text(desc, style: TextStyle(fontSize: 18)),
SizedBox(height: 10,), Image.network(imageURL) ], ), ); }}Copy the code
Note: All content will be published on our official website. Later, Flutter will also update other technical articles, including TypeScript, React, Node, Uniapp, MPvue, data structures and algorithms, etc. We will also update some of our own learning experiences