学习内容:
Flutter 核心思想:“一切皆 Widget”
两种基础 Widget:
StatelessWidget(无状态,静态 UI)、StatefulWidget(有状态,动态 UI)实践任务:
用
StatelessWidget写一个静态页面:显示 “我的第一个 Flutter 页面”+ 一张图片用
StatefulWidget改写计数器 Demo:点击按钮数字 + 1,标题显示当前数字
一、Flutter核心思想:“一切皆Widget”※
1. 什么是Widget※
核心定义:Widget是Flutter中UI的基本构建块,是“描述UI的配置信息”(不是实际渲染对象,实际渲染由RenderObject处理)。
通俗理解:所有可见的(文本、图片、按钮)和不可见的(布局、动画控制器)元素都是Widget,通过组合Widget形成完整页面。
2. “一切皆Widget”的具体体现※
可见元素:Text(文本)、Button(按钮)、Image(图片)、Container(容器)等
布局结构:Row(水平布局)、Column(垂直布局)、Stack(层叠布局)等
样式控制:Padding(内边距)、Margin(外边距,通过Container的margin属性)、FontSize(字体大小,通过TextStyle)等
交互逻辑:GestureDetector(手势检测)、InkWell(点击水波纹)等
import 'package:flutter/material.dart';
void main()
{
runApp(MyApp());
}
// 根Widget:整个应用的入口
class MyApp extends StatelessWidget
{
@override
Widget build(BuildContext context)
{
// MaterialApp:提供Material Design风格的基础配置(标题、主题等)
return MaterialApp(
title: '一切皆Widget',
home: Scaffold( // Scaffold:页面内基础结构(包含AppBar、body等)
appBar: AppBar( // AppBar:顶部导航栏
title: Text('Widget示例'), // Text:文本Widget
),
body: Center( // Center:居中布局Widget
child: Container( // Container:容器Widget(可设置宽高、颜色、边距等)
width: 200,
height: 100,
color: Colors.yellow,
child: Text(
'我是文本',
style: TextStyle( // TextStyle:文本样式Widget
color: Colors.white,
fontSize: 20,
),
),
),
)
)
);
}
}运行效果如下(基于Edge浏览器):

二、StatelessWidget:无状态组件※
1. 核心特性※
- 无状态:创建后属性不可变(内部状态不会变化),UI是静态的。
- 生命周期简单:只有一个build方法,初始化时调用一次,之后不会重新构建(除非父Widget重建)。
- 适用场景:展示固定内容(如:标题、静态图片、固定文本的卡片)。
2. 如何创建StatelessWidget※
(1)定义一个类继承StatelessWidget
(2)重写build方法(返回一个Widget,描述UI结构)
(3)通过构造函数接收外部参数(通常用final修饰,确保不可变)
import 'package:flutter/material.dart';
void main() => runApp(
MaterialApp(
home: Scaffold(
body: StatelessDemo(
title: 'Flutter基础',
content: 'StatelessWidget是无状态组件,UI不会自动变化',
)
)
)
);
// 无状态组件:展示固定信息的卡片
class StatelessDemo extends StatelessWidget
{
// 用final修饰属性,确保不可改变
final String title;
final String content;
final Color color;
// 构造函数:接收外部参数(required表示必传)
const StatelessDemo({
super.key,
required this.title,
required this.content,
this.color = Colors.yellow, // 默认值
});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16), // 内边距Widget
child: Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration( // 装饰Widget(设置背景、圆角等)
color: color,
borderRadius: BorderRadius.circular(8)
),
child: Column( // 垂直布局Widget
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
),
SizedBox(height: 18), // 间距Widget
Text(content),
],
),
),
);
}
}运行效果如下:

三、StatefulWidget:有状态组件※
1. 核心特性※
- 有状态:内部有可变状态(State),状态变化时UI会重新渲染。
- 生命周期复杂:包含initState(初始化)、build(构建UI)、setState(更新状态)、dispose(销毁)等阶段。
- 适用场景:需要动态更新的UI(如:计数器、表单输入、切换显示内容)。
2. 如何创建StatefulWidget※
- 定义一个类继承StatefulWidget(通常作为“壳”,不存储状态)
- 定义一个对应的State类(继承State<MyWidget>),存储可变状态
- 在State类中重写build方法,通过setState更新状态(触发UI重建)
(1)示例1:基础计数器※
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(
home: Scaffold(
body: CounterDemo(),
),
));
// 有状态组件的“壳”
class CounterDemo extends StatefulWidget{
const CounterDemo({super.key});
@override
State<CounterDemo> createState() => _CounterDemoState();
}
// 状态类:存储可变状态,处理逻辑
class _CounterDemoState extends State<CounterDemo> {
// 定义可变状态(计数器值)
int _count = 0;
// 初始化方法:组件创建时调用一次
@override
void initState() {
super.initState();
// 生产环境不建议用print
print('计数器初始化');
}
// 构建UI:状态变化时会重新调用
@override
Widget build(BuildContext context) {
print('UI重新构建,当前计数:$_count');
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'当前计数:$_count',
style: TextStyle(fontSize: 24),
),
SizedBox(height: 16),
ElevatedButton( // 按钮Widget(可点击)
onPressed: () {
// 用setState更新状态:触发build方法重新执行,UI更新
setState(() {
_count++;
});
},
child: Text('点击加1'),
)
],
),
);
}
// 组件销毁时调用(如:页面关闭)
@override
void dispose() {
super.dispose();
print('计数器销毁');
}
}运行效果如下:

(2)示例2:动态切换文本※
import 'package:flutter/material.dart';
void main() => runApp(MaterialApp(home: Scaffold(body: ToggleTextDemo())));
class ToggleTextDemo extends StatefulWidget {
const ToggleTextDemo({super.key});
@override
State<ToggleTextDemo> createState() => _ToggleTextDemoState();
}
class _ToggleTextDemoState extends State<ToggleTextDemo> {
// 状态1:是否显示第一句文本
bool _showFirstText = true;
// 状态2:文本颜色
Color _textColor = Colors.yellow;
// 切换文本内容
void _toggleText() {
setState(() {
_showFirstText = !_showFirstText;
});
}
// 切换文本颜色
void _changeColor() {
setState(() {
_textColor = _textColor == Colors.yellow ? Colors.red : Colors.yellow;
});
}
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16),
child: Column(
children: [
Text(
// 根据状态显示不同的文本
_showFirstText ? '我是第一句' : '我是第二句',
style: TextStyle(fontSize: 20, color: _textColor),
),
SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _toggleText,
child: Text('切换文本'),
),
SizedBox(width: 16),
ElevatedButton(onPressed: _changeColor, child: Text('切换颜色'))
],
)
],
),
);
}
}运行效果:

四、Stateless与Stateful对比※
核心对照区别表
| 特性 | StatelessWidget | StatefulWidget |
| 状态是否可变 | 不可变(属性用final修饰) | 可变(状态存储在State类中) |
| 重建触发条件 | 仅父Widget重建时 | 调用setState()或父Widget重建时 |
| 适用场景 | 静态UI(固定文本、图片) | 动态UI(计数器、表单、切换内容) |
| 生命周期方法 | 只有build() | initState()、build()、dispose()等 |
五、综合实战※
需求:创建一个页面,包含:
- 顶部静态标题
- 中间动态计数器
- 底部静态说明文本
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('widget组合示例')),
body: Column(
children: [
// 静态标题(Stateless)
StaticTitle(title: '今日学习进度'),
// 动态计数器
Expanded(child: StudyCounter()),
// 静态说明(Stateless)
StaticDescription(
text: '提示:点击按钮增加学习次数,每天坚持!'
)
],
),
),
);
}
}
// 静态标题组件(Stateless)
class StaticTitle extends StatelessWidget {
final String title;
const StaticTitle({super.key, required this.title});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(16),
child: Text(
title,
style: TextStyle(fontSize: 22, fontWeight: FontWeight.bold),
),
);
}
}
// 动态计数器组件(Stateful)
class StudyCounter extends StatefulWidget {
const StudyCounter({super.key});
@override
State<StudyCounter> createState() => _StudyCounterState();
}
class _StudyCounterState extends State<StudyCounter> {
int _studyCounter = 0;
void _increment() => setState(() {
_studyCounter++;
});
@override
Widget build(BuildContext context) {
return Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'已学习$_studyCounter次',
style: TextStyle(fontSize: 24, color: Colors.yellow),
),
SizedBox(height: 16),
ElevatedButton(onPressed: _increment, child: Text('点击完成一次学习'))
],
),
);
}
}
// 静态说明组件(Stateless)
class StaticDescription extends StatelessWidget {
final String text;
const StaticDescription({super.key, required this.text});
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.all(12),
child: Text(
text,
style: TextStyle(color: Colors.yellow[600]),
),
);
}
}运行效果如下:
