flutter 创建一个项目后,代码目录结构介绍信息如下:

创建一个项目后,选择了安卓、IOS、web后,生成的代码目录结构如下

所有平台共用同一个 Dart 入口:lib/main.dart; android/、ios/、web/ 只是平台壳工程(嵌入器),负责启动 Flutter 引擎、平台权限、打包配置,不是业务代码入口Flutter

一、目录分别代表什么

your_project/
├── lib/                 ✅ 【核心业务dart代码】
│   └── main.dart        ✅ Flutter全局入口(安卓/iOS/Web都从这里跑)
├── android/             🤖 Android平台壳
├── ios/                 🍎 iOS平台壳
├── web/                 🌐 Web网页平台壳
├── test/                单元测试
├── pubspec.yaml         依赖、资源、版本配置(最重要配置文件)
├── build/               编译输出产物,不要手动改
└── .dart_tool/          dart工具缓存,忽略

1. android/ 安卓目录

  • android/app/src/main/AndroidManifest.xml:安卓清单,权限、包名、Activity 声明、应用图标、启动页
  • android/app/build.gradle:gradle 打包配置、签名、版本号、minSdk、targetSdk
  • android/app/src/main/kotlin/.../MainActivity.kt:安卓原生 Activity,是安卓侧原生入口,作用:创建 FlutterEngine、加载 Flutter 页面,一般不用改

流程:安卓系统启动 MainActivity → 启动 Flutter 引擎 → 引擎去执行 lib/main.dart 的 main ()

2. ios/iOS 目录

  • ios/Runner/Info.plist:iOS 配置,权限、BundleId、图标、白名单、屏幕方向
  • ios/Runner/AppDelegate.swift:iOS 原生 AppDelegate,iOS 原生入口,负责初始化 Flutter 引擎、生命周期、通知回调

流程:iOS 启动 Runner.app → 执行 AppDelegate → 拉起 Flutter 引擎 → 执行 lib/main.dart

3. web/ Web 目录

  • web/index.html:网页 html 宿主,Web 原生入口
  • 里面有 flutter.js 加载脚本,作用:浏览器加载 html 后,js 加载编译后的 dart.js,启动 Flutter

流程:浏览器打开 index.html → flutter.js 加载 Flutter runtime → 执行 lib/main.dart

✅ 重点区分:

  • 平台原生入口:MainActivity.kt / AppDelegate.swift / index.html(平台系统识别的启动点)
  • Flutter 业务入口:lib/main.dart(Flutter 框架统一入口,写界面、业务从这里开始)

二、入口文件最低可运行代码

✅ 1. lib/main.dart(所有平台共用,最低最简可运行)

import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: Scaffold(
        body: Center(child: Text("Hello Flutter")),
      ),
    );
  }
}

解释:main() 是 dart 程序固定入口函数;runApp() 是 Flutter 函数,挂载根 Widget


✅ 2. Android 原生入口 MainActivity.kt(默认最低,几乎不用改)

package com.example.xxx

import io.flutter.embedding.android.FlutterActivity

class MainActivity: FlutterActivity() {
}

继承 FlutterActivity,自动帮你初始化 Flutter 引擎,是安卓最小实现。

✅ 3. iOS 原生入口 AppDelegate.swift(默认最简)

import Flutter
import UIKit

@main
@objc class AppDelegate: FlutterAppDelegate {
  override func application(
    _ application: UIApplication,
    didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
  ) -> Bool {
    GeneratedPluginRegistrant.register(with: self)
    return super.application(application, didFinishLaunchingWithOptions: launchOptions)
  }
}

✅ 4. web/index.html 最简(web 宿主)

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Flutter Web</title>
  <script src="flutter.js" defer></script>
</head>
<body>
  <script>
    _flutter.loader.loadEntrypoint({
      onEntrypointLoaded: async (engineInitializer) => {
        let appRunner = await engineInitializer.initializeEngine();
        await appRunner.runApp();
      }
    });
  </script>
</body>
</html>

三、启动链路总结(非常容易记)

  1. 安卓:系统 → MainActivity → Flutter 引擎 → main.dart
  2. iOS:系统 → AppDelegate → Flutter 引擎 → main.dart
  3. Web:浏览器 → index.html + flutter.js → Flutter 引擎 → main.dart

开发 99% 场景:只改 lib 下面 dart 代码;只有平台权限、打包签名、原生插件、渠道配置才去碰 android /ios/web 目录。

创建好项目后,默认的启动文件代码如下:

import 'package:flutter/material.dart';

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

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

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // TRY THIS: Try running your application with "flutter run". You'll see
        // the application has a purple toolbar. Then, without quitting the app,
        // try changing the seedColor in the colorScheme below to Colors.green
        // and then invoke "hot reload" (save your changes or press the "hot
        // reload" button in a Flutter-supported IDE, or press "r" if you used
        // the command line to start the app).
        //
        // Notice that the counter didn't reset back to zero; the application
        // state is not lost during the reload. To reset the state, use hot
        // restart instead.
        //
        // This works for code too, not just values: Most code changes can be
        // tested with just a hot reload.
        colorScheme: .fromSeed(seedColor: Colors.deepPurple),
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

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

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

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

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

  void _incrementCounter() {
    setState(() {
      // This call to setState tells the Flutter framework that something has
      // changed in this State, which causes it to rerun the build method below
      // so that the display can reflect the updated values. If we changed
      // _counter without calling setState(), then the build method would not be
      // called again, and so nothing would appear to happen.
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      appBar: AppBar(
        // TRY THIS: Try changing the color here to a specific color (to
        // Colors.amber, perhaps?) and trigger a hot reload to see the AppBar
        // change color while the other colors stay the same.
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        // Here we take the value from the MyHomePage object that was created by
        // the App.build method, and use it to set our appbar title.
        title: Text(widget.title),
      ),
      body: Center(
        // Center is a layout widget. It takes a single child and positions it
        // in the middle of the parent.
        child: Column(
          // Column is also a layout widget. It takes a list of children and
          // arranges them vertically. By default, it sizes itself to fit its
          // children horizontally, and tries to be as tall as its parent.
          //
          // Column has various properties to control how it sizes itself and
          // how it positions its children. Here we use mainAxisAlignment to
          // center the children vertically; the main axis here is the vertical
          // axis because Columns are vertical (the cross axis would be
          // horizontal).
          //
          // TRY THIS: Invoke "debug painting" (choose the "Toggle Debug Paint"
          // action in the IDE, or press "p" in the console), to see the
          // wireframe for each widget.
          mainAxisAlignment: .center,
          children: [
            const Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

Flutter的设计思想是:一切皆Widget

在Flutter中自定义组件其实就是一个类,这个类需要继承StatelessWidget/StatefulWidget

StatelessWidget 是无状态组件,状态不可变的widget

StatefulWidget 是有状态组件,持有的状态可能在widget生命周期改变

StatelessWidget(无状态):界面上的内容不会变。比如图标、背景文字、图片,它们只是显示出来,不需要根据用户点击就改变颜色或数字。

•
StatefulWidget(有状态):如果加一个需求——“点击按钮,星星图标变成红色”,那就需要 StatefulWidget 来管理“是否点击过”这个状态了

我们改成这个文件代码如下也可以

需求是:在手机屏幕(或模拟器)的正中央显示一行文字 "Flutter msg"

import 'package:flutter/material.dart'; //引入主包,引入 Flutter 的 Material Design 组件库,有了它才能用 Text、Center 这些组件

//main 函数是 Dart/Flutter 程序的入口,程序一启动就会执行这里的代码
void main() {
  //runApp里面可以是一个组件, runApp() 用来启动 Flutter 应用,它需要一个 Widget(组件)作为参数
  /**这里直接把一个 Center 组件传进去,意味着整个应用目前就只显示这个 Center 及其内容
   * Center 是 Flutter 中的一个布局组件(Widget)。
   * 作用:它会让自己的子组件(child)在水平和垂直方向上都处于正中间。
类比:就像你把一张便利贴贴在了一面墙的正中央。
使用场景:当你想让某个元素(比如文字、图片、按钮)在屏幕或某个容器里居中显示时,就用 Center 把它包起来。

child 是 Flutter 里非常常见的一个属性名,中文意思就是“孩子/子组件”。

含义:在 Flutter 中,很多组件(比如 Center、Container、Padding、Scaffold 等)只能包含一个直接的孩子,这个孩子的名字就统一叫 child。
对应概念:如果一个组件能包含多个孩子,那个属性通常就叫 children(注意多了个 s,是个列表)
   * */

  runApp(
    Center(
      child: new Text(
        "Flutter msg", // 显示的文字内容
        textAlign: TextAlign.left, // 文字在它自己的空间内靠左对齐
        textDirection: TextDirection.ltr, // 文字方向:从左到右(left to right)
        style: TextStyle(
          color: Color.fromARGB(255, 201, 8, 50),//第一个是参数是透明度,后面3个是RGB颜色值
          fontSize: 30.0,//字体大小
          fontWeight: FontWeight.w900,//控制文字笔画的粗细程度
        ),
      ),

      // child 属性:指定 Center 里面要放什么子组件(这里放了一个 Text 文本组件)
    ),
  );
}

图片中的悬浮框是 VS Code(或类似编辑器)显示的代码提示(悬浮信息),它展示的是 Flutter 源码中 Center 组件的构造函数定义。

代码里能写 child:,是因为 child 本身就是这些参数中的一个。以下是具体的对应关系:

1. 图片里其实有 child

仔细看悬浮框里的第三行参数,写着:

Widget? child,

  • Widget? 是参数的类型(表示这里需要传入一个 Widget 组件,问号表示可以为空)。
  • child 就是参数的名字。

悬浮框里的其他参数含义:

  • Key? key,:组件的唯一标识键。
  • double? widthFactor,:宽度缩放倍数。
  • double? heightFactor,:高度缩放倍数。

底部的英文说明 Creates a widget that centers its child.(创建一个将其子组件居中的组件)也印证了这一点。

快速修复是免费的,点右边的修复要登录,可能是调用AI功能修复的

修复后的代码如下

import 'package:flutter/material.dart'; //引入主包,引入 Flutter 的 Material Design 组件库,有了它才能用 Text、Center 这些组件

//main 函数是 Dart/Flutter 程序的入口,程序一启动就会执行这里的代码
void main() {
  //runApp里面可以是一个组件, runApp() 用来启动 Flutter 应用,它需要一个 Widget(组件)作为参数
  /**这里直接把一个 Center 组件传进去,意味着整个应用目前就只显示这个 Center 及其内容
   * Center 是 Flutter 中的一个布局组件(Widget)。
   * 作用:它会让自己的子组件(child)在水平和垂直方向上都处于正中间。
类比:就像你把一张便利贴贴在了一面墙的正中央。
使用场景:当你想让某个元素(比如文字、图片、按钮)在屏幕或某个容器里居中显示时,就用 Center 把它包起来。

child 是 Flutter 里非常常见的一个属性名,中文意思就是“孩子/子组件”。

含义:在 Flutter 中,很多组件(比如 Center、Container、Padding、Scaffold 等)只能包含一个直接的孩子,这个孩子的名字就统一叫 child。
对应概念:如果一个组件能包含多个孩子,那个属性通常就叫 children(注意多了个 s,是个列表)
   * */

  runApp(
    Center(
      child: Text(
        "Flutter msg", // 显示的文字内容
        textAlign: TextAlign.left, // 文字在它自己的空间内靠左对齐
        textDirection: TextDirection.ltr, // 文字方向:从左到右(left to right)
        style: TextStyle(
          color: Color.fromARGB(255, 201, 8, 50),//第一个是参数是透明度,后面3个是RGB颜色值
          fontSize: 30.0,//字体大小
          fontWeight: FontWeight.w900,//控制文字笔画的粗细程度
        ),
      ),

      // child 属性:指定 Center 里面要放什么子组件(这里放了一个 Text 文本组件)
    ),
  );
}

在 Flutter 里:

  • 只能装一个组件时,属性名叫做 child(单数,后面直接跟一个 Widget)。
  • 可以装多个组件时,属性名叫做 children(复数,后面跟一个 Widget 列表 [])

场景

属性名

传值方式

常见组件

单个子组件

child

child: Text(...)

Center, Container, Padding

多个子组件

children

children: [Text(...), Text(...)]

Column, Row, Stack, ListView

多组件写法举例(使用 Column 垂直排列)

Column 是一个可以让子组件从上到下垂直排列的布局组件,它接受的就是 children(多个孩子)

import 'package:flutter/material.dart';

void main() {
  runApp(
    Center(
      // Center 还是只有一个 child
      child: Column(
        // Column 可以包含多个子组件,所以用 children
        // mainAxisSize: MainAxisSize.min 表示 Column 高度只包住内容,不撑满全屏
        mainAxisSize: MainAxisSize.min,
        
        // children 后面是中括号 [],里面可以放任意多个 Widget
        children: [
          Text("第一个文本", textDirection: TextDirection.ltr),
          Text("第二个文本", textDirection: TextDirection.ltr),
          Text("第三个文本", textDirection: TextDirection.ltr),
        ],
      ),
    ),
  );
}

运行效果:

屏幕正中间会显示三行文字,垂直排列:

第一个文本

第二个文本

第三个文本

因为 children 要求的是一个 List<Widget>(Widget 列表),而 Flutter 里几乎所有的东西(文本、图片、按钮、图标、容器、甚至别的布局)全部都是 Widget,所以它们可以随意混搭组合,混合了多种不同类型组件的例子如下:

import 'package:flutter/material.dart';

void main() {
  runApp(
    Center(
      child: Column(
        mainAxisSize: MainAxisSize.min, // 让 Column 高度只包住内容
        
        // children 里放了一个列表,里面混合了 4 种完全不同的组件
        children: [
          
          // 1. 图标组件 (Icon)
          Icon(
            Icons.star,           // 使用 Flutter 自带的星星图标
            color: Colors.orange, // 图标颜色
            size: 50,             // 图标大小
          ),

          // 2. 容器组件 (Container) —— 相当于一个“万能盒子”,可以设置背景色、边距等
          Container(
            margin: EdgeInsets.all(10),   // 外边距
            padding: EdgeInsets.all(10),  // 内边距
            color: Colors.lightBlue[100], // 背景色
            child: Text("这是一个带蓝色背景的文字"), // Container 里面再用 child 放了一个 Text
          ),

          // 3. 图片组件 (Image) —— 这里用网络图片举例
          Image.network(
            'https://picsum.photos/200/100', // 随便一个网络图片地址
            width: 200,
            height: 100,
          ),

          // 4. 按钮组件 (ElevatedButton)
          ElevatedButton(
            onPressed: () {
              // 按钮点击事件(暂时为空)
            },
            child: Text('我是一个按钮'), // 按钮里面也是用 child 放了一个 Text
          ),

        ],
      ),
    ),
  );
}

组件名

类型

作用

Column

布局组件

让子组件垂直排列(用的是 children)

Icon

展示组件

显示 Material 风格的图标

Container

布局/装饰组件

用来给子组件添加背景色、边距、尺寸限制等

Image.network

展示组件

显示网络图片

ElevatedButton

交互组件

一个可点击的凸起按钮

Text

展示组件

显示文字(被嵌套在了 Container 和 ElevatedButton 里面)

核心概念:万物皆可嵌套

从上面的例子你会发现两个很有趣的点:

  1. children 列表里什么都能装:图标、容器、图片、按钮,随意混搭。
  2. 组件可以无限嵌套:
    • Column 用的是 children(因为要装多个)。
    • Container 和 ElevatedButton 自己里面又用了 child(因为它们各自只装一个内部元素,比如一段文字)。
    • 这种“大盒子套小盒子”的方式,就是 Flutter 构建界面的核心逻辑。

当 children 里的组件越来越多、嵌套越来越深时,代码就会变得很长很难读。这时候就正好用得上你最开始提取的那段知识——把其中一部分内容单独抽离成一个自定义组件(继承 StatelessWidget)。

比如,你可以把上面那个 Column 里的“图标+文字+图片”抽离成一个 MyCard 组件,然后 children 里只需要写一句 MyCard() 就行了,代码会瞬间清爽很多

重构后的完整代码

我们把之前那一堆混在一起的代码,拆成了两个自定义组件:一个负责整体布局(MyHomeWidget),一个负责显示那组混合内容(MyCard)

// 1️⃣ 引入 Flutter 的 Material Design 组件库
// 有了它,才能用 MaterialApp、Scaffold、Center、Column、Icon、Container 这些组件
import 'package:flutter/material.dart';

// ============================================================
// 2️⃣ main 函数:Dart/Flutter 程序的入口
// 程序一启动,就会从 main() 开始执行
// ============================================================
void main() {
  // runApp():Flutter 的启动函数,把传入的 Widget 作为根组件渲染到屏幕上
  runApp(
    // ✅ MaterialApp:Flutter 应用的根组件(必须)
    // 作用:
    //   - 自动提供 Directionality(解决文字/图标方向报错)
    //   - 提供主题、路由、本地化等基础配置
    //   - 如果不包 MaterialApp,Icon/Text 等组件会报红屏错误
    MaterialApp(
      // home:指定应用的首页(也就是一启动看到的页面)
      home: Scaffold(
        // Scaffold:页面脚手架,提供了标准的页面结构
        // 它内部可以放 appBar(顶部导航栏)、body(页面主体)、floatingActionButton 等
        // 这里我们主要用它的 body 属性来放内容
        body: Center(
          // Center:让它的子组件在屏幕正中间(水平+垂直都居中)
          // child:只能放【一个】子组件
          child: MyHomeWidget(), // 调用我们自定义的主页面组件
        ),
      ),
    ),
  );
}

// ============================================================
// 3️⃣ 自定义组件 1:MyHomeWidget(主页面内容)
// StatelessWidget:无状态组件
//   - 意思是:这个组件一旦创建,内部数据就不会再变了(静态的)
//   - 适合用来展示固定内容、布局组合
//   - 必须重写 build() 方法,Flutter 通过 build() 知道要画什么
// ============================================================
class MyHomeWidget extends StatelessWidget {
  // build 方法:每次组件需要渲染时,Flutter 会自动调用它
  // BuildContext context:组件的上下文,用来获取主题、尺寸、导航等信息
  @override
  Widget build(BuildContext context) {
    // Column:垂直布局组件,把子组件从上到下排列
    return Column(
      // mainAxisSize:主轴(垂直方向)占多大空间
      // MainAxisSize.min:只占用刚好够用的高度(包裹内容)
      // 如果写 MainAxisSize.max(默认),会撑满整个屏幕高度
      mainAxisSize: MainAxisSize.min,

      // children:子组件列表,可以放【多个】组件
      children: [
        // 复用我们自定义的 MyCard 组件(下面定义的)
        // 这里相当于"画了第一个卡片"
        MyCard(),

        // SizedBox:空白间距组件
        // 这里创建一个高 20 像素的透明盒子,用来在两个卡片之间留空隙
        SizedBox(height: 20),

        // 再画第二个卡片
        MyCard(),
      ],
    );
  }
}

// ============================================================
// 4️⃣ 自定义组件 2:MyCard(一个卡片,包含图标+文字+图片+按钮)
// 同样是无状态组件,只负责展示
// ============================================================
class MyCard extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // 内部也用 Column 让内容垂直排列
    return Column(
      mainAxisSize: MainAxisSize.min, // 只占用刚好需要的高度
      children: [
        // ---------- 1. 图标 ----------
        Icon(
          Icons.star,              // 图标样式:星星(Flutter 内置的 Material 图标)
          color: Colors.orange,    // 图标颜色:橙色
          size: 50,               // 图标大小:50×50 像素
        ),

        // ---------- 2. 带背景的文字容器 ----------
        Container(
          // margin:外边距,Container 和其他组件之间的距离
          margin: EdgeInsets.all(10),   // 上下左右各 10 像素的外边距

          // padding:内边距,文字和 Container 边框之间的距离
          padding: EdgeInsets.all(10),   // 上下左右各 10 像素的内边距

          // color:背景颜色
          // Colors.lightBlue[100]:浅蓝色(100 是色阶,数值越大颜色越深,最大 900)
          color: Colors.lightBlue[100],

          // child:Container 里面放的子组件
          child: Text("这是一个带蓝色背景的文字"),
          // Text:文字组件,直接显示一段文本
        ),

        // ---------- 3. 网络图片 ----------
        Image.network(
          // 图片的网络地址(从互联网加载)
          'https://picsum.photos/200/100',
          // 注意:如果手机/模拟器网络不好,图片可能加载失败显示破裂图标

          width: 200,   // 图片宽度 200 像素
          height: 100,  // 图片高度 100 像素
          // 如果不指定宽高,图片会按原始尺寸显示
        ),

        // ---------- 4. 按钮 ----------
        ElevatedButton(
          // onPressed:点击事件回调
          // 当用户点击按钮时,花括号里的代码会执行
          // 现在里面是空的({}),所以点击不会有任何反应
          // 以后可以写:onPressed: () { print('按钮被点了'); }
          onPressed: () {},

          // child:按钮上显示的内容
          child: Text('我是一个按钮'),
          // ElevatedButton:凸起按钮(有阴影、有背景色)
          // 还有 TextButton(文字按钮)、OutlinedButton(边框按钮)等其他样式
        ),
      ],
    );
  }
}

效果如下:

还有另一个组件如下

import 'package:flutter/material.dart'; //引入主包,引入 Flutter 的 Material Design 组件库,有了它才能用 Text、Center 这些组件

//main 函数是 Dart/Flutter 程序的入口,程序一启动就会执行这里的代码
void main() {
  //runApp里面可以是一个组件, runApp() 用来启动 Flutter 应用,它需要一个 Widget(组件)作为参数
  /**这里直接把一个 Center 组件传进去,意味着整个应用目前就只显示这个 Center 及其内容
   * Center 是 Flutter 中的一个布局组件(Widget)。
   * 作用:它会让自己的子组件(child)在水平和垂直方向上都处于正中间。
类比:就像你把一张便利贴贴在了一面墙的正中央。
使用场景:当你想让某个元素(比如文字、图片、按钮)在屏幕或某个容器里居中显示时,就用 Center 把它包起来。

child 是 Flutter 里非常常见的一个属性名,中文意思就是"孩子/子组件"。

含义:在 Flutter 中,很多组件(比如 Center、Container、Padding、Scaffold 等)只能包含一个直接的孩子,这个孩子的名字就统一叫 child。
对应概念:如果一个组件能包含多个孩子,那个属性通常就叫 children(注意多了个 s,是个列表)
   * */

  runApp(
    MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text("Flutter标题"), backgroundColor: Colors.red),
        body: MyApp(),
      ),
    ),
  );
}

//无状态组件
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        "Flutter msg", // 显示的文字内容
        textAlign: TextAlign.left, // 文字在它自己的空间内靠左对齐
        textDirection: TextDirection.ltr, // 文字方向:从左到右(left to right)
        style: TextStyle(
          color: Color.fromARGB(255, 11, 11, 146), //第一个是参数是透明度,后面3个是RGB颜色值
          fontSize: 30.0, //字体大小
          fontWeight: FontWeight.w900, //控制文字笔画的粗细程度
        ),
      ),

      // child 属性:指定 Center 里面要放什么子组件(这里放了一个 Text 文本组件)
    );
  }
}

为什么属性名不一样?

这是 Flutter 的设计约定,记住就行:

组件

属性名

原因

Scaffold

body

它不只放一个东西,还有 appBar、floatingActionButton 等,所以用"身体"这个语义名

Center

child

它只放一个东西,统一叫 child

Container

child

它只放一个东西,统一叫 child

Column / Row

children(复数+s)

能放多个东西,所以用复数

💡 本质都一样:都是"往这个组件里塞一个(或几个)子组件"

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐