今天来学习flutter的几个基本组件

基础组件

Scaffold组件

DART已复制
import 'package:flutter/material.dart'; //导入Material包

void main() {
  runApp(
    MaterialApp(
      title: "终末地AI群聊",
      theme: ThemeData(scaffoldBackgroundColor: Colors.lightBlueAccent),
      home: Scaffold(),
    ),
  );
}

上一篇我们学到的这个里有个Scaffold组件

​ image-20260420132350772

这里我们

DART已复制
import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        //头部
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
	   //中部
        body: Container(child: Center(child: Text("终末地AI群聊"))),
		//底部
        bottomNavigationBar: Container(
          height: 80.0,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    ),
  );
}

​ image-20260420135410738

  • MaterialApp包裹整个应用形成统一的Material Design风格
  • Scoffold组件可快速搭建页面骨架,如appBar、body、bottomNavigationBar等
  • Container用来作为容器,设置高度(height),child用来存放子组件
  • Text是用来显示文本的组件

自定义组件(Customwidget)

​ image-20260420142055618

其实

  • StatelessWidget = 静态组件(数据显示后自己不会变)
  • StatefulWidget = 动态组件(数据变了,界面会跟着变)

无状态组件(StatelessWidget)

创建一个新的类,继承StatelessWidget类并实现build方法

build返回一个Widget

DART已复制
import 'package:flutter/material.dart';

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

//无状态组件
class MainPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    return MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
        body: Container(child: Center(child: Text("终末地AI群聊"))),
        bottomNavigationBar: Container(
          height: 80,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    );
  }
}

​ image-20260420145629323

DART已复制
class Chatpage extends StatelessWidget{
  @override
  Widget build(BuildContext context) {
    // TODO: implement build
    throw UnimplementedError();
  }
}

我们把这个拆开来看

class Chatpage extends StatelessWidget继承 StatelessWidget,即定义了一个组件 Chatpage

Widget build(BuildContext context)必须重写 build(),这个的作用是返回要显示的UI,Flutter 会在 runApp();调用这个函数画界面

而return .....;返回值是Widget类型,因为在flutter里面所有的组件都是widget类型

这里我们注意

“程序入口” = 应用从哪里开始跑 在flutter中就是runApp(这里必须是“根组件”)
“组件” = 页面里的一块积木,根组件就是MaterialApp

而所有组件必须在根组件里使用

main() → 启动
MyApp → 应用壳子
MaterialApp → App框架
Scaffold → 页面结构
Text / Button → UI组件

DART已复制
import 'package:flutter/material.dart';

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

// 无状态主页面
class MainPage extends StatelessWidget {
  const MainPage({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: const Text("终末地AI群聊")),
        body: const Center(child: MyText(title: "终末地AI群聊")),
        bottomNavigationBar: Container(
          height: 80,
          alignment: Alignment.center,
          child: const Text("底部栏"),
        ),
      ),
    );//返回值是整个MaterialApp框架内所有东西
  }
}

// 自定义无状态组件
class MyText extends StatelessWidget {
  final String title;

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

  @override
  Widget build(BuildContext context) {
    return Text(title, style: const TextStyle(fontSize: 24)); //返回值是Text组件
  }
}

​ image-20260420150951795

有状态组件(StatefulWidget)

有状态组件是构建动态交互界面的核心,能够管理变化的内部状态,当状态改变时,逐渐会更新显示内容

DART已复制
class MainPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    // TODO: implement createState
    throw UnimplementedError();
  }
}

class MainPage extends StatefulWidget 继承 StatelfulWidget,即定义了一个组件 Chatpage

Widget build(BuildContext context)必须重写 build(),这个的作用是返回要显示的UI,Flutter 会在 runApp();调用这个函数画界面

而return .....;返回值是Widget类型,因为在flutter里面所有的组件都是widget类型

​ image-20260425122640439

DART已复制
import 'package:flutter/material.dart';

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

class MainPage extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return _MainPageState();
  }
}

class _MainPageState extends State<MainPage> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
        body: Container(child: Center(child: Text("终末地AI群聊"))),
        bottomNavigationBar: Container(
          height: 80,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    );
  }
}

快速创建无状态组件和有状态组件的方法

首先下载这仨插件

​ image-20260425123143670

然后我们在VScode中使用statelessW 和statefulW按回车就可以快速创建

​ image-20260425123543708

这里补充一个知识,在VScode中批量变量名或者方法名的方式有以下几种

场景 推荐方法
少量变量 Ctrl + D
当前文件全部 Ctrl + Shift + L
整个项目 Ctrl + Shift + H
最安全(推荐) ⭐ F2
DART已复制
import 'package:flutter/material.dart';

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

class TestWidget extends StatefulWidget {
  const TestWidget({super.key});

  @override
  State<TestWidget> createState() => _TestWidgetState();
}

class _TestWidgetState extends State<TestWidget> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
        body: Container(child: Center(child: Text("终末地AI群聊"))),
        bottomNavigationBar: Container(
          height: 80,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    );
  }
}

组件生命周期-无状态组件

无状态组件的生命周期只有一个阶段——build方法

这个阶段的过程是:

① 创建(构造函数)

Flutter 创建这个组件实例

DART已复制
MyWidget({super.key});

② build(构建 UI)

DART已复制
@override
Widget build(BuildContext context) {
  return Text("Hello");
}

唯一核心生命周期方法

当组件被创建或者父组件状态变化导致其需要重新构建时,build方法会被调用

DART已复制
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
        body: Container(child: Center(child: Text("终末地AI群聊"))),
        bottomNavigationBar: Container(
          height: 80,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    );
  }
}

组件生命周期-有状态组件

​ image-20260425132140323

​ image-20260425132230255

有状态组件 = 可以随时间改变 UI 的组件

DART已复制
class MyWidget extends StatefulWidget

生命周期过程如下:创建 → initState → build →(多次 setState → build)→ dispose

DART已复制
import 'package:flutter/material.dart';

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

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  //创建阶段 createState方法会被调用一次,创建一个状态对象
  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  //初始化阶段 initState方法会被调用一次,进行一些初始化操作
  @override
  void initState() {
    super.initState();
  }

  //依赖变化阶段 didChangeDependencies方法会被调用一次,进行一些依赖变化的操作
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  //构建阶段 build方法会被调用多次,进行构建UI的操作
  @override
  Widget build(BuildContext context) {
    return Container();
  }

  //更新阶段 didUpdateWidget方法会被调用多次,进行一些更新操作
  @override
  void didUpdateWidget(covariant MainPage oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  //停用阶段 deactivate方法会被调用一次,进行一些停用操作
  @override
  void deactivate() {
    super.deactivate();
  }

  //销毁阶段 dispose方法会被调用一次,进行一些销毁操作
  @override
  void dispose() {
    super.dispose();
  }
}
  • 无状态组件-build
  • 有状态组件(创建阶段):createState->initState->didchangeDependencies->build
  • 有状态组件(更新阶段):didUpdateWidget->build
  • 有状态组件(销毁阶段):deactivate->dispose
  • 执行一次函数:createState、initState、dispose
  • Inheritedwidget:专门用于在Widget树中自顶向下高效地共享数据,顶层组件提供数据,子孙节点直接获取

事件-点击事件GestureDetector

事件:用户与应用程序交互时触发的各种动作,比如触摸屏幕、滑动、点击等

点击事件:当点击某个元素触发的动作

常规方案:GestureDetector是Flutter中最常用、功能最丰富的手势检测组件

用法:使用GestureDetector包裹被点击的元素,传入onTap方法

​ image-20260425140015128

DART已复制
import 'package:flutter/material.dart';

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

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  //创建阶段 createState方法会被调用一次,创建一个状态对象
  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  //初始化阶段 initState方法会被调用一次,进行一些初始化操作
  @override
  void initState() {
    super.initState();
  }

  //依赖变化阶段 didChangeDependencies方法会被调用一次,进行一些依赖变化的操作
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  //构建阶段 build方法会被调用多次,进行构建UI的操作
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
        body: Container(
          child: Center(
            //鼠标点击事件GestureDetector
            child: GestureDetector(
              //onTap就是单击事件,onDoubleTap就是双击事件
              onTap: () {
                // 处理点击事件
                print("群聊按钮被单击");
              },
              onDoubleTap: () {
                print("群聊按钮被双击");
              },
              child: Text("点击加入群聊"),
            ),
          ),
        ),
        bottomNavigationBar: Container(
          height: 80,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    );
  }

  //更新阶段 didUpdateWidget方法会被调用多次,进行一些更新操作
  @override
  void didUpdateWidget(covariant MainPage oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  //停用阶段 deactivate方法会被调用一次,进行一些停用操作
  @override
  void deactivate() {
    super.deactivate();
  }

  //销毁阶段 dispose方法会被调用一次,进行一些销毁操作
  @override
  void dispose() {
    super.dispose();
  }
}

事件-组件点击事件

​ image-20260425140944928

​ image-20260425141623743

DART已复制
import 'package:flutter/material.dart';

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

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  //创建阶段 createState方法会被调用一次,创建一个状态对象
  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  //初始化阶段 initState方法会被调用一次,进行一些初始化操作
  @override
  void initState() {
    super.initState();
  }

  //依赖变化阶段 didChangeDependencies方法会被调用一次,进行一些依赖变化的操作
  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  //构建阶段 build方法会被调用多次,进行构建UI的操作
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
        body: Container(
          child: Center(
            //TextButton 文本按钮组件
            child: TextButton(
              onPressed: () {
                setState(() {
                  //更新状态,触发重新构建UI
                  print("按钮被点击了");
                });
              },
              child: Text("按钮"),
            ),
          ),
        ),
        bottomNavigationBar: Container(
          height: 80,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    );
  }

  //更新阶段 didUpdateWidget方法会被调用多次,进行一些更新操作
  @override
  void didUpdateWidget(covariant MainPage oldWidget) {
    super.didUpdateWidget(oldWidget);
  }

  //停用阶段 deactivate方法会被调用一次,进行一些停用操作
  @override
  void deactivate() {
    super.deactivate();
  }

  //销毁阶段 dispose方法会被调用一次,进行一些销毁操作
  @override
  void dispose() {
    super.dispose();
  }
}

状态更新-setState

语法:数据的变化要更新UI视图,需要执行setState方法,setState方法会造成build的重新执行。

告诉 Flutter:数据变了,请重新调用 build() 刷新界面

例如我们写一个计数器

DART已复制
import 'package:flutter/material.dart';

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

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  // 计数器
  int count = 0;
    
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
        body: Center(
          //Row就是让这三个组件(即"减"+"数字"+"加"排成一条线)
          child: Row(
            children: [
              TextButton(
                onPressed: () {
                  count -= 1;
                  print(count);
                },
                child: Text("减"),
              ),
              //将count转换为字符串
              Text(count.toString()),
              //
              TextButton(
                onPressed: () {
                  count += 1;
                  print(count);
                },
                child: Text("加"),
              ),
            ],
          ),
        ),
        bottomNavigationBar: Container(
          height: 80,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    );
  }
}

此时我们发现点击加减号时中间的数字不会改变,这是因为我们没有添加setState状态监测

此时我们加上serState,然后点击加或者减就会看到中间的数字发生改变

DART已复制
import 'package:flutter/material.dart';

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

class MainPage extends StatefulWidget {
  const MainPage({super.key});

  @override
  State<MainPage> createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  // 计数器
  int count = 0;
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "终末地AI群聊",
      home: Scaffold(
        appBar: AppBar(centerTitle: true, title: Text("终末地AI群聊")),
        body: Center(
          child: Row( 
            children: [
              TextButton(
                onPressed: () {
                  //此时增加状态检测
                  setState(() {
                    count -= 1;
                    print(count);
                  });
                  //也可以这么写,因为这个是异步操作,setState为让程序重新执行build方法
                  //count -= 1;
                  //print(count);
                  //setState(() {});
                  
                },
                child: Text("减"),
              ),
              Text(count.toString()),
              TextButton(
                onPressed: () {
                  //此时增加状态监测
                  setState(() {
                    count += 1;
                    print(count);
                  });
                  //也可以这么写
                  //count -= 1;
                  //print(count);
                  //setState(() {});
                },
                child: Text("加"),
              ),
            ],
          ),
        ),
        bottomNavigationBar: Container(
          height: 80,
          child: Center(child: Text("终末地AI群聊")),
        ),
      ),
    );
  }
}

​ image-20260425144108495