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:

  • chooseStart 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 directorylibFolder, which contains the Flutter code we wrote;
  • I opened it and found one insidemain.dartIt is what we start the FlutterEntrance to the fileAnd 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 lotDon't knowDo 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:

  • butNo 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 programThe entry is the main functionDart writes Flutter, so the entry to Flutter is also main.
  • But we importedWhat is Material?
  • Also, we call one in the main functionRunApp () functionWhat 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 applicationWhat you seeAlmost all widgets, evenInside margin setting, we also need to use a name calledThe Padding of the WidgetTo 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 pushingDesign style, orDesign language,The design specificationAnd so on;
  • There are a lot of design specifications, likecolor,Typesetting of text,Respond to animation with transitions,fillAnd so on;
  • It’s highly integrated in FlutterMaterial 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 doesThe navigation barThere will be someThe background colorEtc.

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 isThe scaffoldScaffolding 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 asappBarandbody;
  • AppBar is for designing the navigation bar, and we passed in oneThe 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 noticedNested too muchDon’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