Skip to main content

Widget

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

Widget

#

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

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( // 根 Widget
      home: Scaffold(
        appBar: AppBar(
          title: const Text('我的主页'),
        ),
        body: Center(
          child: Builder(
            builder: (context) {
              return Column(
                children: [
                  const Text('Hello, World!'),
                  const SizedBox(height: 20),
                  ElevatedButton(
                    onPressed: () {
                      print('Click!');
                    },
                    child: const Text('一个按钮'),
                  ),
                ],
              );
            },
          ),
        ),
      ),
    );
  }
}

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

Widget 组合

#

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

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

如果你运行前面示例中的代码,Flutter 将绘制一个带有文本“Hello, World!”的按钮,该按钮居中显示在屏幕上,垂直排列。为了定位这些元素,有一个 Center Widget,它将它的子元素定位在可用空间的中心,还有一个 Column Widget,它将它的子元素垂直排列在一起。

显示 Widget 组合的图表,包含一系列线条和节点。

在本系列的下一页中,你将学习更多关于 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 方法;相反,它们的 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 和有状态 Widget,而无需担心丢失状态。父 Widget 不需要保留子 Widget 来保存其状态,而可以在任何时候创建子 Widget 的新实例,而不会丢失子 Widget 的持久状态。框架会完成在适当的时候查找和重用现有状态对象的所有工作。

在本系列后面的状态管理课程中,将有更多关于StatefulWidget 对象的信息。

重要的 Widget

#

Flutter SDK 包含许多内置 Widget,从最小的 UI 片段(如 Text)到布局 Widget,以及样式化应用程序的 Widget。在学习路径中的下一课中,以下 Widget 最重要:

下一步:布局

#

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

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

反馈

#

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