跳至主要内容

部件

要开始使用 Flutter,您需要对 Dart 编程语言(Flutter 应用程序是用它编写的)和 Widget(Flutter UI 的构建块)有所了解。本页面将介绍这两者,但您将在整个系列中继续学习它们。本页面中列出了其他资源,但您无需成为这两个主题的专家即可继续学习。

部件

#

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

Widget 基于组合形成层次结构。每个 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'),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

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

Widget 组合

#

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

有布局 Widget,例如 PaddingAlignmentRowColumnGrid。这些布局 Widget 本身没有视觉表示。相反,它们的唯一目的是控制另一个 Widget 布局的某些方面。Flutter 还包括利用这种组合方法的实用程序 Widget。例如,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 中布局的更多信息。

构建 Widget

#

要在 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 类:有状态 Widget 和无状态 Widget。

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

另一方面,如果 Widget 的唯一特性需要根据用户交互或其他因素发生变化,则该 Widget 就是有状态的。例如,如果 Widget 有一个计数器,每当用户点击按钮时就会递增,则计数器的值就是该 Widget 的状态。当该值发生变化时,需要重建 Widget 以更新其 UI 部分。这些 Widget 是 StatefulWidget 的子类,并且(因为 Widget 本身是不可变的),它们将可变状态存储在一个单独的类中,该类是 State 的子类。StatefulWidgets 没有 build 方法;相反,它们的用户界面是通过其 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 对象的更多信息,请参阅状态管理课程

需要了解的重要 Widget

#

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

下一步:布局

#

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

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

反馈

#

由于本网站的这一部分正在不断发展,我们欢迎您的反馈