The first example of Flutter's official website

Original link

Preface

Learning Flutter, you will surely see the first example on the official website: Chinese  or  English . But as a novice, you may be struggling to read it. The purpose of this article is to help you better understand this example.

The final rendering:

 

 

 

Let's first analyze how to achieve the effect in the figure above:

Android developers

1. Prepare data: List data and selected data can be stored in two lists or arrays respectively. 2. Interface list: Use ListView or RecyclerView 3. Interface jump: Intent can be used to carry data to a new list page

iOS developer

1. Prepare data: List data and selected data can be stored in two arrays respectively. 2. Interface list: use TableView or CollectionView 3. Interface jump: use NavigationController, you can directly assign values ​​to new page objects

in conclusion

We found that whether it is native Android or iOS development, the steps that need to be done are:

  1. Store the data to be displayed, store the selected data
  2. Display the list and display the data
  3. Set to jump to a new page

So in Flutter development, follow these steps to better understand

Flutter development

* Prepare data: List data is stored in an array, and selected data can be stored in Set (because set can automatically remove duplicates). * Interface list: Use ListView * Interface jump: Navigator can be used

Disassemble and analyze the official code, take you quickly to understand

The official website uses about 110 lines of code to implement the above example. We disassembled these codes into three main parts to help us learn:

Prerequisite: You should first use Android studio or other development tools to create a Flutter project. If you need to learn about this step, you can  learn quickly here

When you create a brand new Flutter project and run it, the familiar "Hello world" will appear on the interface. In order to make it easier to understand Flutter's code, let's analyze the initial creation code first, at least to know where we need to start:

 

 

 

What we want to edit is the main.dart  file here  . Like other languages, the entry function of Flutter is the main function:

import 'package:flutter/material.dart';
 
void main() => runApp(new MyApp());   //分析 1
 
class MyApp extends StatelessWidget {  //分析 2 (StatelessWidget)
  @override
  Widget build(BuildContext context) {   //分析 3
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(      //分析 4
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(  //分析 5
          child: new Text('Hello World'),
        ),
      ),
    );
  }
}

analysis

  1. Here  =>  is a shorthand for the one-line function in Dart, which is equivalent to:
void main() {
  runApp(new MyApp());
} 
  1. StatelessWidget represents a component with only one state, which corresponds to StatefulWidget (which means there may be multiple states). There is no need to delve into the principle here, just know that this is related to flutter's refresh and so on.

  2. In the Widget component, the build method is used to describe its internal structure. The build here means that the system components of MaterialApp are used in the construction of MyApp.

  3. The value of the home tag: Scaffold is a component provided in the Material library, in which we can set the navigation bar, title, and the body attribute of the widget tree containing the home screen. You can see here that AppBar and a Text are added to the page.

  4. Center is a component that can place subcomponents in the center

Start remodeling

Our goal is to replace the TextView displaying hello_world on the page with a ListView. From the above analysis, we can see that replacing the value of the home tag in point 4 above with a ListView can change the content displayed on the page. But before that, we need to prepare the data to be displayed. Here is a  tripartite package called  english_words that can help us generate the displayed word data. First learn how to add dependent packages:

 

 

 

  1. Open the pubspec.yaml file to add a third party library:
dependencies:
  flutter:
    sdk: flutter
 
  cupertino_icons: ^0.1.0
  english_words: ^3.1.0
  1. Click  Packages get to  get the package just added.

After adding the english_words library, you can use this library to create data like this:

//创造5个随机词组,并返回词组的迭代器
generateWordPairs().take(5)

Learn to use StatefulWidget

Looking at the source code of ListView, it is found that it is ultimately inherited from StatelessWidget, so its state is unique. But the data in the ListView to be implemented is dynamically changing, so you need to use the StatefulWidget to dynamically change the data in the ListView.

To use the StatefulWidget component, you need to control the display state in different situations by yourself, so you need to implement the State class to tell the StatefulWidget class how to display it in different situations.

Create a dynamically changing component class to represent the ListView to be displayed:

class RandomWords extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {  //分析1
    return new RandomWordsState();
  }
}

analysis:

  1. The method of creating the State class, here inherits the State of the system to create a class named RandomWordsState to control the display in each state of the ListView.
class RandomWordsState extends State<RandomWords> {
}
  1. 复制代码

To complete the display data and save the clicked data, use array and set to store respectively (use set to store the clicked data because set can be deduplicated, you can also choose other storage methods)

class RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];   //分析 1
  final _saved = new Set<WordPair>();
  final _biggerFont = const TextStyle(fontSize: 18.0);   //分析 2
}

analysis:

  1. Add _ in Dart to indicate privatization
  2. Constant for font size

Create data set and build ListView

Add the following two methods to the RandomWordsState class, which means to create a data set and build a ListView:

Widget _buildSuggestions() {   
    return new ListView.builder(
      padding: const EdgeInsets.all(16.0),
      // 对于每个建议的单词对都会调用一次itemBuilder,然后将单词对添加到ListTile行中
      // 在偶数行,该函数会为单词对添加一个ListTile row.
      // 在奇数行,该函数会添加一个分割线widget,来分隔相邻的词对。
      // 注意,在小屏幕上,分割线看起来可能比较吃力。
      itemBuilder: (context, i) {          
        // 在每一列之前,添加一个1像素高的分隔线widget
        if (i.isOdd) return new Divider();
 
        // 语法 "i ~/ 2" 表示i除以2,但返回值是整形(向下取整),比如i为:1, 2, 3, 4, 5
        // 时,结果为0, 1, 1, 2, 2, 这可以计算出ListView中减去分隔线后的实际单词对数量
        final index = i ~/ 2;
        // 如果是建议列表中最后一个单词对
        if (index >= _suggestions.length) {
          // ...接着再生成10个单词对,然后添加到建议列表
          _suggestions.addAll(generateWordPairs().take(10));   
        }
        return _buildRow(_suggestions[index]);
      }
    );
  }
 
  Widget _buildRow(WordPair pair) {
    final alreadySaved = _saved.contains(pair);
 
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: new Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }

There are detailed comments in the code, but in order to facilitate understanding, here is a little explanation:

  1. The _buildSuggestions method is to return a ListView
  2. The _buildRow method is to return a row in ListView (ListTile) how to display

In the _buildSuggestions method:

  • The itemBuilder in the code is how to display the configuration of a row (ListTile), and its return value is the _buildRow method
  • _suggestions.addAll(generateWordPairs().take(10));It is to add 10 data to the display array each time

In the _buildRow method:

  • Set up a row (ListTile represents a row of content, called cell in iOS and Android) how to display
  • ListTile sets the title, trailing (icon on the right) and click event onTap ()
  • Will determine what icon to display on the right according to whether it has been saved
  • When clicked, the content that has not been clicked will be saved in the _saved container.

Add jump logic

Add the _pushSaved method to indicate how to jump to a new page and display the selected data:

main.dart

void _pushSaved() {
    Navigator.of(context).push(  // 分析 1
      new MaterialPageRoute(  // 分析 2
        builder: (context) {
          final tiles = _saved.map(  //数据
            (pair) {
              return new ListTile(
                title: new Text(
                  pair.asPascalCase,
                  style: _biggerFont,
                ),
              );
            },
          );
          final divided = ListTile.divideTiles(
            context: context,
            tiles: tiles,
          ).toList();
 
          return new Scaffold(  // 分析 3
            appBar: new AppBar(
              title: new Text('Saved Suggestions'),
            ),
            body: new ListView(children: divided),
          );
        },
      ),
    );
  }

Analysis: 1. Use Navigator.of(context).push to handle the jump, the required parameter is a Route 2. Create a page Route 3. Return to a new one, the body content inside is a ListView, which is displayed Data read in _saved

In the end, all code integration looks like this:

 
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';
 
void main() => runApp(new MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      theme: new ThemeData(
        primaryColor: Colors.red,
      ),
      home: RandomWords(),
    );
  }
}
 
class RandomWords extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return new RandomWordsState();
  }
}
 
class RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];
  final _saved = new Set<WordPair>();
  final _biggerFont = const TextStyle(fontSize: 18.0);
 
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
      appBar: new AppBar(
        title: new Text('Startup Name Generator'),
        actions: <Widget>[
          new IconButton(icon: new Icon(Icons.list), onPressed: _pushSaved),
        ],
      ),
      body: _buildSuggestions(),
    );
  }
 
  void _pushSaved() {
    Navigator.of(context).push(
      new MaterialPageRoute(
        builder: (context) {
          final tiles = _saved.map(
            (pair) {
              return new ListTile(
                title: new Text(
                  pair.asPascalCase,
                  style: _biggerFont,
                ),
              );
            },
          );
          final divided = ListTile.divideTiles(
            context: context,
            tiles: tiles,
          ).toList();
 
          return new Scaffold(
            appBar: new AppBar(
              title: new Text('Saved Suggestions'),
            ),
            body: new ListView(children: divided),
          );
        },
      ),
    );
  }
 
  Widget _buildSuggestions() {
    return new ListView.builder(
        padding: const EdgeInsets.all(16.0),
        itemBuilder: (context, i) {
          if (i.isOdd) return new Divider();
          final index = i ~/ 2;
          if (index >= _suggestions.length) {
            _suggestions.addAll(generateWordPairs().take(10));
          }
          return _buildRow(_suggestions[index]);
        });
  }
 
  Widget _buildRow(WordPair pair) {
    final alreadySaved = _saved.contains(pair);
 
    return new ListTile(
      title: new Text(
        pair.asPascalCase,
        style: _biggerFont,
      ),
      trailing: new Icon(
        alreadySaved ? Icons.favorite : Icons.favorite_border,
        color: alreadySaved ? Colors.red : null,
      ),
      onTap: () {
        setState(() {
          if (alreadySaved) {
            _saved.remove(pair);
          } else {
            _saved.add(pair);
          }
        });
      },
    );
  }
}

Run it, you can see the top effect.

Guess you like

Origin blog.csdn.net/qq_41619796/article/details/114886840