Take you to read Flutter Demo (flutter nanny-level introductory tutorial)

dart、flutter
Analysis of Flutter Demo

- Article information -
Author: Jack Lee (jcLee95)
Visit me at: https://jclee95.blog.csdn.net
Email: [email protected].
Shenzhen China
Address of this article:https://blog.csdn.net/qq_28550263/article/details/131390277

【介绍】:本文带你阅读 Flutter Demo,并全面解析其中涉及的相关知识点。

[Tip]: The effect demonstration is at the end of this article


1 Overview

2. Part 1: Material import and main function

2.1 Look at the code

This part of the code is:

import 'package:flutter/material.dart';

void main() {
    
    
  runApp(const MyApp());
}

2.2 Import Material

import 'package:flutter/material.dart';

This line of code imports Flutter's Material library, which provides a large number of predefined UI components and styles, allowing us to quickly build applications with Material Design style.

2.2 main function

program entry

void main() {
    
    
  runApp(const MyApp());
}

The main() function is the entry point to a Dart program. In this function, we call the runApp() method and pass a constant instance of the MyApp class. runAppThe () method takes the incoming Widget (component) as the root Widget of the application and starts building the Widget tree. Here, we use the custom MyApp Widget as the root Widget of the application .

runApp function

runApp()function is the startup function of the Flutter application. It accepts a Widget parameter, which is the root Widget of the application. When the function is called runApp(), Flutter will attach the incoming Widget to the rendering tree and start building and displaying the entire Widget tree. This function is usually called in the application's main()function to be executed when the application starts.

runApp()The relevant information of the function is as follows:

project describe
parameter runApp()The function accepts a Widget parameter, this Widget is usually a custom root Widget , which contains the entire UI structure of the application.
Function runApp()The function attaches the incoming Widget as the root Widget to the rendering tree. Then, Flutter starts to build and display the entire Widget tree, starting from the root Widget , and building each sub- Widget step by step .
usage runApp()Functions are typically called within an application's main()function to be executed when the application starts.

For example:

import 'package:flutter/material.dart';

void main() {
    
    
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    
    
  
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Hello World')),
        body: Center(child: Text('Welcome to my app!')),
      ),
    );
  }
}

In this example, runApp()the function main()is called within the function, passing an MyAppinstance of the class. MyAppIs a custom root Widget that contains the UI structure of the entire application.

3. The second part: the stateless component MyApp class

3.1 Look at the code

This part of the code is:

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

  // 这个 widget 是您应用程序的根。
  
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // 这是您应用程序的主题。
        //
        // 尝试一下:尝试使用 "flutter run" 运行您的应用程序。您会看到
        // 应用程序具有蓝色的工具栏。然后,在不退出应用的情况下,
        // 尝试将下面 colorScheme 中的 seedColor 更改为 Colors.green,
        // 然后调用 "hot reload"(保存更改或按下 Flutter 支持的 IDE 中的 "hot
        // reload" 按钮,或者如果您使用了命令行启动应用程序,则按 "r")。
        //
        // 注意计数器没有重置为零;应用程序状态在重新加载期间不会丢失。
        // 要重置状态,请使用热重启代替。
        //
        // 这对代码也同样适用,而不仅仅是值:大多数代码更改都可以
        // 通过热重载进行测试。
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter演示主页'),
    );
  }
}

3.2 Inherit StatelessWidget class

The following is an analysis of the Flutter code:

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

This code defines a MyAppclass called that inherits from StatelessWidget. StatelessWidgetis an immutable Widget that describes a portion of the application's UI. MyAppThe class has a constructor that takes an keyoptional parameter named and passes it to the superclass StatelessWidget's constructor.

3.3 build method of StatelessWidget class

  
  Widget build(BuildContext context) {
    
    

Here we override the method StatelessWidgetin the class build. buildA method is a Widgetfunction returning a that takes a BuildContextparameter. BuildContextIs an object representing the position of the current Widget in the Widget tree. This method will be called when Flutter needs to build this Widget.

    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter演示主页'),
    );
  }
}

In buildthe method, we return a MaterialAppWidget. MaterialAppis a handy top-level widget that includes many of the basic components needed for a Material Design-style app. It accepts the following parameters:

  • title: The title of the application, usually used for the task manager or window title.

  • theme: The theme data for the application. Here we use ThemeDatathe class to create a custom theme where:

    • colorScheme: Use ColorScheme.fromSeed()the method to generate a Colors.deepPurplecolor scheme based on .
    • useMaterial3: Set to trueto use the Material 3 style in the application.
  • home: The home screen widget of the application. Here, we created a MyHomePagecustom widget called and set its title to "Flutter Demo Home".

In StatelessWidgetthe class, buildmethod is a method that describes the part of the user interface represented by this Widget. It describes the user interface by building a composition of other widgets that describe the user interface in a more concrete way. The build process recursively proceeds until the description of the user interface is fully concrete. The framework calls this method when this Widget is inserted into a given BuildContextand when this Widget's dependencies change (for example, the that this Widget references InheritedWidgetchanges).

In practice, buildthe method's main purpose is to return a new Widget that describes the application's user interface. Usually, this method will contain some conditional logic to generate different widgets according to the parameters passed in or external state. This makes StatelessWidgetis a very flexible building block that can be used to create complex user interfaces.


Widget build(BuildContext context) {
    
    
  // 在此处返回一个新的 Widget,描述应用程序的用户界面。
}

3.4 @override annotation in Dart language

For annotations in the dart language, you can refer to the blog post "Dart Notes: Annotations in the Dart Language"

@overrideThe annotation is used to indicate that the method of the subclass overrides the method of the parent class. This helps ensure that superclass methods are correctly overridden when refactoring code. The Dart analyzer will issue a warning if it is not covered correctly.

3.5 MaterialApp top-level components

MaterialAppis a handy top-level widget that encapsulates some of the basic components required for a Material Design-style app, such as navigation, theming, and routing. It inherits from the WidgetsAppclass and provides some functionality related to Material Design. Here are MaterialAppsome of the main properties of and their explanations:

Attributes type Defaults describe reference link
title String ‘’ The title of the application that will be displayed in the operating system's task switcher. MaterialApp.title
home Widget null The application's default page, usually the first page displayed when the application starts. MaterialApp.home
theme ThemeData null The application's global theme. You can define your own ThemeDataobjects to customize the application's colors, fonts, button styles, and more. MaterialApp.theme
color Color null The primary color used by applications in the operating system interface, such as Android's task switcher. Used if not set ThemeData.primaryColor. MaterialApp.color
routes Map<String, WidgetBuilder> null The application's routing table, which defines page navigation within the application. The routing table is a mapping of strings to WidgetBuilder, where the string represents the route name, and WidgetBuilder is a BuildContextfunction that accepts and returns a Widget. MaterialApp.routes
initialRoute String null The initial route name for the application. If set initialRoute, this route will be navigated to on startup instead of using homethe attribute. MaterialApp.initialRoute
onGenerateRoute RouteFactory null A callback function used to generate routes based on the given route settings. Use this property if you need to use dynamic routing or parameterized routing in your application. MaterialApp.onGenerateRoute
onUnknownRoute RouteFactory null A callback function to handle routesroutes not found in the table. Usually used to display a "404 Page Not Found" error page. MaterialApp.onUnknownRoute
navigatorKey GlobalKey<NavigatorState> null NavigatorThe global key associated with the application's . NavigatorUse this property if you need access from other parts of your application . MaterialApp.navigatorKey
builder TransitionBuilder null A callback function that can insert a Widget on top of the application's routes. This is useful for widgets that need to be displayed application-wide, such as dialogs or overlays. MaterialApp.builder
localizationsDelegates List<LocalizationsDelegate<dynamic>> null A LocalizationsDelegatelist that sets the application's localization resources. MaterialApp.localizationsDelegates
supportedLocales List<Locale> null List of regions supported by the application. MaterialApp.supportedLocales

以下是一个简单的 MaterialApp 示例:

import 'package:flutter/material.dart';

void main() {
    
    
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    
    
  
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
      title: 'My App',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: MyHomePage(),
    );
  }
}

3.6 色彩方案:ColorScheme 类

官方文档位于:https://api.flutter.dev/flutter/material/ColorScheme-class.html

ColorScheme 是一个包含一组用于描述应用程序颜色的属性的类。它是一个不可变的对象,用于定义应用程序中使用的颜色。在 Material Design 中,ColorScheme 用于定义主题的颜色。以下是 ColorScheme 的一些常用属性:

属性 描述
primary 应用程序主要部分的背景颜色。例如,工具栏和浮动操作按钮。
primaryVariant 主要颜色的较暗版本。
secondary 应用程序次要部分的背景颜色。例如,选项卡栏。
secondaryVariant 次要颜色的较暗版本。
surface 卡片和抽屉等表面元素的背景颜色。
background 应用程序背景颜色。
error 错误状态和异常情况下使用的颜色。
onPrimary 显示在主要颜色上的文本和图标的颜色。
onSecondary 显示在次要颜色上的文本和图标的颜色。
onSurface 显示在表面颜色上的文本和图标的颜色。
onBackground 显示在背景颜色上的文本和图标的颜色。
onError 显示在错误颜色上的文本和图标的颜色。
brightness 应用程序的整体亮度。它是一个 Brightness 枚举,可以是 Brightness.lightBrightness.dark

例如:

import 'package:flutter/material.dart';

void main() {
    
    
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
    
    
  
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
      title: 'ColorScheme Demo',
      theme: ThemeData(
        colorScheme: ColorScheme(
          primary: Colors.blue,
          primaryVariant: Colors.blue[700],
          secondary: Colors.orange,
          secondaryVariant: Colors.orange[700],
          surface: Colors.white,
          background: Colors.white,
          error: Colors.red,
          onPrimary: Colors.white,
          onSecondary: Colors.white,
          onSurface: Colors.black,
          onBackground: Colors.black,
          onError: Colors.white,
          brightness: Brightness.light,
        ),
      ),
      home: MyHomePage(),
    );
  }
}

4. 第三部分:有状态组件 MyHomePage

4.1 看代码

这部分代码如下:

class MyHomePage extends StatefulWidget {
    
    
  const MyHomePage({
    
    super.key, required this.title});

  // 这个 widget 是你的应用程序的主页。它是有状态的,这意味着它有一个 State 对象
  // (在下面定义),其中包含影响其外观的字段。

  // 这个类是 state 的配置。它保存了由父级(在本例中是 App widget)提供的值
  // (在本例中是标题),并被 State 的 build 方法使用。Widget 子类中的字段总是
  // 被标记为 "final"。

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

4.2 继承于 StatefulWidget 类

这段代码定义了一个名为 MyHomePageStatefulWidget 类,表示该类为一个 有状态组件

class MyHomePage extends StatefulWidget {
    
    

这一行定义了一个名为 MyHomePage 的类,它继承自 StatefulWidgetStatefulWidget 是 Flutter 中的一种 Widget,它可以在其生命周期内保持可变状态。

const MyHomePage({
    
    super.key, required this.title});

这是 MyHomePage 类的构造函数。它接受两个参数:

  • super.key:这是传递给父类(StatefulWidget)构造函数的可选 key 参数。key 参数用于控制框架如何将新的 Widget 与先前的 Widget 关联起来。通常情况下,您不需要处理 key,除非您在处理有状态的 Widget 或需要对 Widget 树进行优化。
  • required this.title:这是一个必需的 title 参数,它是一个字符串。required 关键字表示调用构造函数时必须提供此参数。this.title 表示将传入的参数值赋给类的 title 属性。

4.3 title 属性

final String title;

这一行定义了一个名为 title 的不可变字符串属性。final 关键字表示一旦初始化后,这个属性将无法更改。

4.4 createState 方法

  
  State<MyHomePage> createState() => _MyHomePageState();

这是 createState 方法,它是 StatefulWidget 类的必需方法。此方法用于创建与此 StatefulWidget 实例关联的状态对象。@override 关键字表示我们在这里重写了父类的方法。State<MyHomePage> createState() => _MyHomePageState(); 表示我们将返回一个名为 _MyHomePageState 的新状态对象。

createState 方法是 StatefulWidget 类的核心方法,它用于创建与 StatefulWidget 实例关联的状态对象。当框架需要构建 StatefulWidget 时,它会调用此方法以创建一个新的状态对象。这个状态对象将在 StatefulWidget 的整个生命周期中保持与之关联。

  • @override:这是一个元数据注解,表示我们将重写父类 StatefulWidget 的方法。在这种情况下,我们重写 createState 方法。这样做的目的是为了提供一个自定义的状态对象,以便在构建我们的 MyHomePage StatefulWidget 时使用。
  • State<MyHomePage> createState():这是我们重写的方法。方法的返回类型是 State<MyHomePage>,表示我们将返回一个与 MyHomePage 类型关联的状态对象。这个状态对象将负责管理与 MyHomePage 实例相关的状态。
  • => _MyHomePageState();:这是一个简化的函数体,等同于 { return _MyHomePageState(); }。箭头函数表示我们将创建一个名为 _MyHomePageState 的新状态对象,并将其作为结果返回。

要了解 createState 方法的重要性,我们需要了解 StatefulWidget 的工作原理。StatefulWidget 是一个具有可变状态的 Widget。当 StatefulWidget 的状态发生变化时,框架会重新构建 Widget 树以反映这些更改。为了实现这一点,框架需要知道如何创建与 StatefulWidget 实例关联的状态对象。这就是 createState 方法的作用:告诉框架如何创建状态对象。

在实际应用中,createState 方法通常会返回一个自定义的 State 子类,该子类包含了与 StatefulWidget 实例关联的状态数据和逻辑。这使得 StatefulWidget 可以在其生命周期内保持状态,从而实现动态 UI、响应事件和执行其他与状态相关的操作。

5. 状态类 _MyHomePageState

5.1 看代码

在上一节中,定义了一个名为 MyHomePage 的 有状态组件(继承于StatefulWidget 类)。其 createState 方法中使用了一个名为 _MyHomePageState状态类,该类将在创建 MyHomePage 实例时与其关联。

_MyHomePageState 类是一个自定义的 State 子类,负责管理与 MyHomePage 实例相关的状态。它包含一个 _counter 属性,表示按下按钮的次数,以及一个 _incrementCounter 方法,用于更新 _counter 的值。它还实现了 build 方法,用于构建与 MyHomePage 实例关联的 UI。

_MyHomePageState 类的代码如下:

class _MyHomePageState extends State<MyHomePage> {
    
    
  int _counter = 0;

  void _incrementCounter() {
    
    
    setState(() {
    
    
      // 这个对 setState 的调用告诉 Flutter 框架,这个 State 中的某些内容已经发生了变化,
      // 这将导致它重新运行下面的 build 方法,以便显示可以反映更新后的值。如果我们更改了
      // _counter 而没有调用 setState(),那么 build 方法将不会再次被调用,因此什么都不会发生。
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    
    
    // 每次调用 setState 时,例如上面的 _incrementCounter 方法所做的,
    // 都会重新运行此方法。

    // Flutter 框架已经过优化,以使得重新运行 build 方法变得更快,
    // 因此你可以重建任何需要更新的内容,而不是必须单独更改 widget 实例。
    return Scaffold(
      appBar: AppBar(
        // 尝试一下:尝试将这里的颜色更改为特定颜色(例如 Colors.amber?),
        // 然后触发热重载以查看 AppBar 的颜色变化,而其他颜色保持不变。

        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // 这里我们从由 App.build 方法创建的 MyHomePage 对象中获取值,
        // 并将其用于设置我们的 appbar 标题。
        title: Text(widget.title),
      ),
      body: Center(
        // Center 是一个布局 widget。它接受一个子 widget,并将其定位
        // 在父 widget 的中央。
        child: Column(
          // Column 也是一个布局 widget。它接受一组子 widget,并垂直排列它们。
          // 默认情况下,它会自动调整自身尺寸以适应其子 widget 水平方向的尺寸,
          // 并尽量与其父 widget 一样高。

          // Column 具有各种属性来控制它如何调整自身尺寸以及如何定位其子 widget。
          // 在这里,我们使用 mainAxisAlignment 将子 widget 垂直居中;主轴在这里
          // 是垂直轴,因为 Column 是垂直的(交叉轴将是水平的)。

          // 尝试一下:调用 "debug painting"(在 IDE 中选择 "Toggle Debug Paint"
          //操作,或者在控制台中按 "p"),以查看每个 widget 的线框。
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              '你已经按了这个按钮很多次了:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // 这个尾随逗号使得自动格式化在构建方法中更加美观。
    );
  }
}

_MyHomePageState 类应该继承自 State 类,并实现 build 方法以构建与 MyHomePage 实例关联的 UI。

5.2 State 类

State 类的官方文档地址为:https://api.flutter.dev/flutter/widgets/State-class.html

在Flutter中,State类是与StatefulWidget相关的一个重要概念。State对象存储了一个StatefulWidget的可变状态。当状态改变时,State对象会通知Flutter框架重建UI。

State类的生命周期包括以下几个阶段:

阶段 描述
created State对象被创建时,State.initState方法会被调用。
initialized State对象被创建,但还没有准备构建时,State.didChangeDependencies在这个时候会被调用。
ready State对象已经准备好了构建,State.dispose没有被调用的时候。
defunct State.dispose被调用后,State对象不能够被构建。

要改变State对象的状态,可以使用setState方法。setState方法接受一个回调函数,该函数对状态进行修改。当回调函数执行完毕后,Flutter框架将安排重建UI。

下面是一个简单的例子,演示了如何使用State类和setState方法:

class Counter extends StatefulWidget {
    
    
  
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
    
    
  int _count = 0;

  void _incrementCounter() {
    
    
    setState(() {
    
    
      _count = _count + 1;
    });
  }

  
  Widget build(BuildContext context) {
    
    
    return Column(
      children: [
        Text('You have pushed the button this many times:'),
        Text('$_count', style: Theme.of(context).textTheme.headline4),
        ElevatedButton(
          onPressed: _incrementCounter,
          child: Text('Increment Counter'),
        ),
      ],
    );
  }
}

在这个例子中,_CounterState类维护了一个名为_count的状态。当用户点击按钮时,_incrementCounter方法会被调用,使用setState方法更新_count的值。这将触发Flutter框架重建UI,以显示更新后的计数值。

5.3 提升按钮:ElevatedButton组件

这是 Flutter 提供的诸多按钮中的一种,其前身为 凸起按钮:RaisedButton组件RaisedButton现在已经被废弃,官方推荐使用 ElevatedButton 替代。

关于 Flutter 的各种按钮类组件及其详细用法的更多介绍,请参考博文《Flutter 组件(三)按钮类组件》https://blog.csdn.net/qq_28550263/article/details/131387856


F. 附录

F.1 Flutter Demo 完整源代码

import 'package:flutter/material.dart';

void main() {
    
    
  runApp(const MyApp());
}

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

  // 这个 widget 是您应用程序的根。
  
  Widget build(BuildContext context) {
    
    
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // 这是您应用程序的主题。
        //
        // 尝试一下:尝试使用 "flutter run" 运行您的应用程序。您会看到
        // 应用程序具有蓝色的工具栏。然后,在不退出应用的情况下,
        // 尝试将下面 colorScheme 中的 seedColor 更改为 Colors.green,
        // 然后调用 "hot reload"(保存更改或按下 Flutter 支持的 IDE 中的 "hot
        // reload" 按钮,或者如果您使用了命令行启动应用程序,则按 "r")。
        //
        // 注意计数器没有重置为零;应用程序状态在重新加载期间不会丢失。
        // 要重置状态,请使用热重启代替。
        //
        // 这对代码也同样适用,而不仅仅是值:大多数代码更改都可以
        // 通过热重载进行测试。
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter演示主页'),
    );
  }
}

class MyHomePage extends StatefulWidget {
    
    
  const MyHomePage({
    
    super.key, required this.title});

  // 这个 widget 是你的应用程序的主页。它是有状态的,这意味着它有一个 State 对象
  // (在下面定义),其中包含影响其外观的字段。

  // 这个类是 state 的配置。它保存了由父级(在本例中是 App widget)提供的值
  // (在本例中是标题),并被 State 的 build 方法使用。Widget 子类中的字段总是
  // 被标记为 "final"。

  final String title;

  
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
    
    
  int _counter = 0;

  void _incrementCounter() {
    
    
    setState(() {
    
    
      // 这个对 setState 的调用告诉 Flutter 框架,这个 State 中的某些内容已经发生了变化,
      // 这将导致它重新运行下面的 build 方法,以便显示可以反映更新后的值。如果我们更改了
      // _counter 而没有调用 setState(),那么 build 方法将不会再次被调用,因此什么都不会发生。
      _counter++;
    });
  }

  
  Widget build(BuildContext context) {
    
    
    // 每次调用 setState 时,例如上面的 _incrementCounter 方法所做的,
    // 都会重新运行此方法。

    // Flutter 框架已经过优化,以使得重新运行 build 方法变得更快,
    // 因此你可以重建任何需要更新的内容,而不是必须单独更改 widget 实例。
    return Scaffold(
      appBar: AppBar(
        // 尝试一下:尝试将这里的颜色更改为特定颜色(例如 Colors.amber?),
        // 然后触发热重载以查看 AppBar 的颜色变化,而其他颜色保持不变。

        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // 这里我们从由 App.build 方法创建的 MyHomePage 对象中获取值,
        // 并将其用于设置我们的 appbar 标题。
        title: Text(widget.title),
      ),
      body: Center(
        // Center 是一个布局 widget。它接受一个子 widget,并将其定位
        // 在父 widget 的中央。
        child: Column(
          // Column 也是一个布局 widget。它接受一组子 widget,并垂直排列它们。
          // 默认情况下,它会自动调整自身尺寸以适应其子 widget 水平方向的尺寸,
          // 并尽量与其父 widget 一样高。

          // Column 具有各种属性来控制它如何调整自身尺寸以及如何定位其子 widget。
          // 在这里,我们使用 mainAxisAlignment 将子 widget 垂直居中;主轴在这里
          // 是垂直轴,因为 Column 是垂直的(交叉轴将是水平的)。

          // 尝试一下:调用 "debug painting"(在 IDE 中选择 "Toggle Debug Paint"
          //操作,或者在控制台中按 "p"),以查看每个 widget 的线框。
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              '你已经按了这个按钮很多次了:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ), // 这个尾随逗号使得自动格式化在构建方法中更加美观。
    );
  }
}

F.2 效果演示

在这里插入图片描述

Guess you like

Origin blog.csdn.net/qq_28550263/article/details/131390277