要开始使用 Flutter,您需要熟悉 Dart 编程语言(Flutter 应用程序是用其编写的)和 Widgets(它们是 Flutter UI 的构建块)。本页将介绍这两者,但您将在本系列中继续学习每个主题。本页中列出了其他资源,但您无需精通这两个主题即可继续学习。

组件

#

对于 Flutter,您会经常听到“一切皆是 widget”。Widgets 是 Flutter 应用用户界面的构建块,每个 widget 都是用户界面一部分的不可变声明。Widgets 用于描述用户界面的所有方面,包括文本和按钮等物理方面,以及填充和对齐等布局效果。

Widgets 通过组合形成层次结构。每个 widget 都嵌套在其父级内部,并且可以从父级接收上下文。这种结构一直延续到根 widget,如下面的简单示例所示:

Dart
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp( // Root widget
      home: Scaffold(
        appBar: AppBar(
          title: const Text('My Home Page'),
        ),
        body: Center(
          child: Builder(
            builder: (context) {
              return Column(
                children: [
                  const Text('Hello, World!'),
                  const SizedBox(height: 20),
                  ElevatedButton(
                    onPressed: () {
                      print('Click!');
                    },
                    child: const Text('A button'),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

在前面的代码中,所有实例化的类都是 Widgets:MaterialAppScaffoldAppBarTextCenterBuilderColumnSizedBoxElevatedButton

Widget 组合

#

如前所述,Flutter 强调将 Widgets 作为组合单元。Widgets 通常由许多其他小型、单一用途的 Widgets 组成,这些 Widgets 结合起来可以产生强大的效果。

PaddingAlignmentRowColumnGrid 等布局 Widgets。这些布局 Widgets 本身没有视觉表现。相反,它们唯一目的是控制另一个 widget 的布局的某些方面。Flutter 还包含利用这种组合方法的实用 Widgets。例如,常用的 Container widget 由多个负责布局、绘制、定位和大小的 widget 组成。一些 widget 具有视觉表现,例如前面示例中的 ElevatedButtonText,以及 IconImage 等 widget。

如果您运行前面示例中的代码,Flutter 将绘制一个按钮,上面显示“Hello, World!”文本,垂直布局并居中显示在屏幕上。为了定位这些元素,有一个 Center widget,它将其子项放置在可用空间的中心,以及一个 Column widget,它将其子项垂直地一个接一个地布局。

A diagram that shows widget composition with a series of lines and nodes.

在本系列的下一页中,您将了解更多关于 Flutter 布局的信息。

构建 Widgets

#

要在 Flutter 中创建用户界面,您需要重写 widget 对象上的 build 方法。所有 widget 都必须有一个 build 方法,并且它必须返回另一个 widget。例如,如果您想在屏幕上添加一些带填充的文本,可以这样编写:

Dart
class PaddedText extends StatelessWidget {
  const PaddedText({super.key});

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: const Text('Hello, World!'),
    );
  }
}

当创建此 widget 时以及此 widget 的依赖项(例如传递到 widget 中的状态)发生变化时,框架会调用 build 方法。此方法可能在每一帧中被调用,并且除了构建 widget 之外不应有任何副作用。要了解有关 Flutter 如何渲染 widget 的更多信息,请查阅 Flutter 架构概述

Widget 状态

#

框架引入了两种主要的 widget 类型:有状态 (stateful) 和无状态 (stateless) widget。

没有可变状态(即没有随时间变化的类属性)的 Widgets 继承自 StatelessWidget。许多内置 widget 都是无状态的,例如 PaddingTextIcon。当您创建自己的 widget 时,大多数时候都会创建 Stateless widget。

另一方面,如果 widget 的独特特性需要根据用户交互或其他因素而改变,那么该 widget 就是有状态的 (stateful)。例如,如果一个 widget 有一个计数器,每次用户点击按钮时都会递增,那么计数器的值就是该 widget 的状态。当该值改变时,需要重建该 widget 以更新其 UI 部分。这些 widget 继承自 StatefulWidget,并且(因为 widget 本身是不可变的)它们将可变状态存储在一个单独的继承自 State 的类中。StatefulWidgets 没有 build 方法;相反,它们的 UI 是通过它们的 State 对象构建的,如下面的示例所示。

Dart
class CounterWidget extends StatefulWidget {
  @override
  State<CounterWidget> createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State<CounterWidget> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }
  
  @override
  Widget build(BuildContext context) {
    return Text('$_counter');
  }
}

每当您修改 State 对象(例如,通过递增计数器)时,您都必须调用 setState 来通知框架通过再次调用 Statebuild 方法来更新用户界面。

将状态与 widget 对象分离,可以让其他 widget 以完全相同的方式对待无状态和有状态 widget,而无需担心丢失状态。父级无需为了保留子级状态而持有子级,它可以在任何时候创建子级的新实例,而不会丢失子级的持久状态。框架会负责在适当的时候查找和重用现有状态对象的所有工作。

关于 StatefulWidget 对象的更多信息将在本系列的后续内容中,在状态管理课程中介绍。

重要的 Widgets

#

Flutter SDK 包含许多内置 widget,从最小的 UI 片段(如 Text)到布局 widget,以及用于设置应用程序样式的 widget。在学习路径中进入下一课时,以下 widget 是最重要的需要了解的。

下一页:布局

#

本页介绍了 Flutter 的基础概念,例如 widgets,并帮助您熟悉阅读 Flutter 和 Dart 代码。即使您对遇到的每个主题感觉不完全清楚也没关系,因为本页之后的每页都将深入探讨特定主题。在下一节中,您将通过在 Flutter 中创建更复杂的布局来开始构建更有趣的 UI。

如果您想练习本页所学到的信息,可以阅读使用 Flutter 构建用户界面

反馈

#

随着本网站此部分的不断发展,我们欢迎您的反馈