https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1/#0

介绍

Flutter是谷歌推出的移动开发SDK,用于快速在iOS和Android上制作高质量的原生界面。 Flutter及其代码,被世界各地的开发人员和组织使用,并且是免费和开源的。

在此教程中,您将创建一个简单的Flutter应用程序。如果您熟悉面向对象的代码和基本编程概念(如变量,循环和条件),则可以完成此codelab。您不需要以前使用Dart或移动编程的经验。

part1中将会学到什么

  • 如何编写在iOS和Android上看起来很自然的Flutter应用程序。
  • Flutter应用程序的基本结构。
  • 查找和使用包来扩展功能。
  • 使用热重载可以加快开发周期。
  • 如何实现有状态小部件(stateful widget)。
  • 如何创建一个无限(infinite)的,延迟加载的列表(lazily loaded list)。

在此codelab的第2部分中,您将添加交互性,修改应用程序的主题,并添加导航到新页面的功能(在Flutter中称为route)。

part1教程中干了啥

创建1个列表无线滚动,滚动时候出现新的名字,如下图:

https://codelabs.developers.google.com/codelabs/first-flutter-app-pt1/img/e3624172607d5551.png

开发环境

创建应用程序

1). 创建名称为’startup_namer’的程序

flutter create startup_namer

2). 将lib/main.dart内容替换为:

import 'package:flutter/material.dart';

void main() => runApp(new MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: const Text('Welcome to Flutter'),
        ),
        body: const Center(
          child: const Text('Hello World'),
        ),
      ),
    );
  }
}

运行后如图:

第一次在物理设备上运行时,可能比较慢。在此之后,您可以使用热重新加载进行快速更新。 如果应用程序正在运行,Save还会执行热重新加载。

分析

  1. 此示例创建一个Material应用程序。 Material是一种视觉设计标准。 Flutter提供了丰富的Material小部件。
  2. main方法使用了胖箭头(=>), 这是dart的语法糖,适用于单行的函数或方法。
  3. Myapp继承了StatelessWidget,使得应用程序本身就是一个Widget。flutter世界中,任何东西都是Widget,包括alignment, padding 以及 layout。
  4. Material库中的脚手架部件(Scaffold widget)提供默认的app bar、title、body(保存主屏幕Widge tree)主体属性。小部件子树(widget subtree)可能非常复杂。
  5. Widget的主要工作是提供一种build方法,该方法描述如何展示相对而言更低widget。
  6. body包含Center Widget,其中Center Widget又含了Text子部件的。Center Widget将其widget subtree与屏幕中心对齐

使用外部package

在这一步中,您将开始使用名为english_words的开源软件包,其中包含几千个最常用的英语单词和一些工具方法。

您可以在pub.dartlang.org上找到english_words包以及许多其他开源软件包。

pubspec文件管理Flutter应用程序的asset。在pubspec.yaml文件中,添加english_words: ^3.1.0到依赖列表。

dependencies:
  flutter:
    sdk: flutter

  cupertino_icons: ^0.1.0
  english_words: ^3.1.0   # add this line

保存后AS会自动拉取。 片刻可以在左侧Packages里看到:

20190130154883189726993.png

dart中导入头文件。AS中,import 'xx'显示灰色的表示未使用。

import 'package:english_words/english_words.dart';

修改代码:

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final wordPair = new WordPair.random(); // Add this line.
    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(    // Change "const" to "new".
          //child: const Text('Hello World'),   // Replace this text...
          child: new Text(wordPair.asPascalCase),  // With this text.
        ),
      ),
    );
  }
}     

(注意:此时CenterText不要用const来修饰)

可以看到,每次重新加载,屏幕上都会显示不同的名字。 这是因为单词配对是在构建方法中生成的,构建方法在每次MaterialApp需要渲染时运行,或者在Flutter Inspector中切换平台时运行(toggling the Platform in Flutter Inspector.)。

添加 stateful widget

Stateless widgets是不可变的,这意味着它们的属性不能改变 - 所有值都是final。而Stateful widgets保存的状态在其生命周期内可以改变。

实现有状态窗口小部件至少需要两个类:一个StatefulWidget类,以及由它创建一个State类的实例。 StatefulWidget类本身是不可变的,但State类在widget的生命周期内持久存在。

在此步骤中,您将添加一个有状态(Stateful)的小部件RandomWords,它创建其StateType,RandomWordsState。然后,您将在现有的MyApp无状态小部件中使用RandomWords作为子项。

1). 创建一个最小的状态类。它可以在MyApp外部的文件中的任何位置,但示例中将其放在文件的底部。添加以下文本:

class RandomWordsState extends State<RandomWords> {
  // TODO Add build method
}

注意声明的State<RandomWords>。这表明是围绕RandomWords的通用State类。应用程序的大多数逻辑和状态都驻留在这里 - 它维护RandomWords小部件的状态。 当用户通过切换心形图标从列表中添加或删除它们时,此类保存生成的单词对,这些单词对随着用户滚动而无限增长。并且可以点击心形喜欢该单词对(在part2教程)。

2). 创建RandomWords

将有状态的RandomWords小部件添加到main.dart。除了创建State类之外,RandomWords小部件几乎没有其他功能:

class RandomWords extends StatefulWidget {
  @override
  RandomWordsState createState() => new RandomWordsState();
}

3). 添加RandomWordsState的build方法:

class RandomWordsState extends State<RandomWords> {
  //必须实现build方法
  @override
  Widget build(BuildContext context) {
    final WordPair wordPair = new WordPair.random();
    return new Text(wordPair.asCamelCase);
  }
}

4). 修改MyApp

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final WordPair wordPair = new WordPair.random();  // Delete this line.

    return new MaterialApp(
      title: 'Welcome to Flutter',
      home: new Scaffold(
        appBar: new AppBar(
          title: new Text('Welcome to Flutter'),
        ),
        body: new Center(
          //child: new Text(wordPair.asPascalCase), // Change this line to... 
          child: new RandomWords(),                 // ... this line.
        ),
      ),
    );
  }
}

创建无线滚动的ListView

ListView的builder工厂构造函数允许您根据需要懒惰地构建列表视图。

1). 创建_suggestions列表保存名字,_biggerFont变量用作字体调整

_修饰的变量为私有变量

class RandomWordsState extends State<RandomWords> {
  // Add the next two lines.
  final List<WordPair> _suggestions = <WordPair>[];
  final TextStyle _biggerFont = const TextStyle(fontSize: 18.0); 
  ...
}

接下来,您将向RandomWordsState类添加_buildSuggestions()函数。 此方法将构建显示建议的单词对的ListView。

ListView类提供了一个构建器属性itemBuilder,它是一个工厂构建器和指定为匿名函数的回调函数。 两个参数传递给函数 - BuildContext和行迭代器,i。迭代器(iterator)从0开始,每次调用函数时递增 - 每个建议的单词配对一次。此模型允许建议列表在用户滚动时无限增长。

2). RandomWordsState类添加_buildSuggestions方法:

Widget _buildSuggestions() {
    return new ListView.builder(
      padding: const EdgeInsets.all(16.0),
      //每个建议的单词对调用的时候都会调用`itemBuilde`, 并将每个建议的单词对放入ListTile行。
      // 对于偶数行,该函数为单词配对添加ListTile行。 对于奇数行,该函数添加一个Divider小部件以显示分割线。
      // 请注意,在较小的设备上可能难以看到分割线。
      itemBuilder: (BuildContext context, int i) {
        //在ListView中的每一行之前添加一个像素高的分隔符小部件。
        if (i.isOdd) {
          return const Divider();
        }
        //语法“i~ / 2”将i除以2并返回整数结果。 例如:1,2,3,4,5变为0,1,1,2,2。
        // 这将计算ListView中减去出去分割线,实际的单词配对数量
        final int index = i ~/ 2;
        //如果你已达到可用单词对的末尾......
        if (index >= _suggestions.length) {
          //..然后生成10个并将它们添加到_suggestions
          _suggestions.addAll(generateWordPairs().take(10));
        }
        return _buildRow(_suggestions[index]);
      },
    );
  }

_buildSuggestions函数每个单词对调用_buildRow一次。此函数在ListTile中显示每个新对,这将允许您在第2部分示例中更有吸引力。

3). 给RandomWordsState添加_buildRow方法。

Widget _buildRow(WordPair pair) {
return new ListTile(
  title: new Text(
    pair.asPascalCase,
    style: _biggerFont,
  ),
);
}

4). 更新RandomWordsState的build方法,以使用_buildSuggestions()。 Scaffold实现了基本的Material Design视觉布局。

  @override
  Widget build(BuildContext context) {
    //final wordPair = new WordPair.random(); // Delete these... 
    //return new Text(wordPair.asPascalCase); // ... two lines.

    return new Scaffold (                   // Add from here... 
      appBar: new AppBar(
        title: new Text('Startup Name Generator'),
      ),
      body: _buildSuggestions(),
    );                                      // ... to here.
  }

5). 更新入口函数MyApp

  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Startup Name Generator',
      home: new RandomWords(),
    );
  }

保存下,可以看到如下:

完整代码:gist

one more thing

以上是part1部分的内容,part2中会做如下工作:

  1. 添加交互性
  2. 添加导航到新route
  3. 修改主题颜色

其他

学习Flutter SDK的其他东西:

更多资源包括:

Please reach out to us at our mailing list. We’d love to hear from you!