1. 核心基石:Widget、State 与 BuildContext
Flutter 的核心设计理念是 “一切皆为 Widget” 。理解以下三个概念是入门的关键。
1.1 Widget:UI 的“蓝图”
Widget 是不可变的(immutable),用于描述 UI 的配置信息。它分为两大类:
StatelessWidget (无状态):静态的,创建后 UI 不再变化(如:文本、图标)。
StatefulWidget (有状态):动态的,持有
State对象,用于存储可变数据并驱动 UI 更新(如:复选框、输入框)。
1.2 State:让 UI“动”起来
当 Widget 需要根据数据变化而重绘时,就需要使用 State。通过调用 setState() 通知框架数据已改变,触发 build 方法重绘。
class _CounterState extends State<Counter> {
int _count = 0; // 状态数据
void _increment() {
setState(() {
_count++; // 修改数据,触发 UI 重建
});
}
// ... build 方法中展示 _count
}1.3 BuildContext:Widget 树中的“定位器”
BuildContext 是每个 Widget 在树中的位置句柄,用于查找父级 Widget 或获取主题、路由等信息。
// 获取屏幕宽度
double width = MediaQuery.of(context).size.width;
// 获取主题色
Color primary = Theme.of(context).primaryColor;
// 页面跳转
Navigator.of(context).push(...);2. 布局组件:搭建 UI 的“脚手架”
Flutter 的布局主要依靠单子组件和多子组件配合。核心规则:约束往下传递,尺寸向上传递,父级决定位置。
2.1 线性布局:Row 与 Column
用于将子组件沿水平或垂直方向排列。
Row / Column 共有属性
示例:
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly, // 均匀分布
crossAxisAlignment: CrossAxisAlignment.center, // 垂直居中
children: [Icon(Icons.home), Text('首页')],
)2.2 弹性布局:Flex 与 Expanded
Expanded 用于填充父级剩余空间,是构建响应式布局的关键。
Expanded 属性
注意: Expanded 只能作为 Row、Column 或 Flex 的直接子组件。
Row(
children: [
Icon(Icons.star),
Expanded(child: Text("这是一段很长的文本,它会占据剩余的所有空间")),
Icon(Icons.arrow_forward),
],
)2.3 层叠布局:Stack 与 Positioned
类似于 Android 的 FrameLayout 或 CSS 的 absolute 定位。
Stack 属性
Positioned 属性
示例:
Stack(
alignment: Alignment.center,
children: [
Container(width: 200, height: 200, color: Colors.grey),
Positioned(bottom: 10, right: 10, child: Text('右下角')),
],
)2.4 万能容器:Container
一个组合了绘制、定位、大小调整的便利组件。常用作设置背景、边距、宽高。
Container 属性
Decoration 常用子类: BoxDecoration
BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
boxShadow: [BoxShadow(blurRadius: 5)],
gradient: LinearGradient(colors: [Colors.red, Colors.blue]),
)示例:
Container(
width: 100,
height: 100,
margin: EdgeInsets.all(10), // 外边距
padding: EdgeInsets.all(8), // 内边距
decoration: BoxDecoration( // 装饰(背景、边框、圆角)
color: Colors.blue,
borderRadius: BorderRadius.circular(8),
boxShadow: [BoxShadow(blurRadius: 5)],
),
child: Text("Hello"),
)3. 基础 UI 组件
3.1 Text:文本显示
Text 属性
TextStyle 常用属性:
TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.red,
fontFamily: 'Roboto',
letterSpacing: 1.2,
height: 1.5, // 行高倍数
)示例:
Text(
'Hello Flutter',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Colors.deepPurple,
),
textAlign: TextAlign.center,
)3.2 Image:图片加载
构造方法(静态工厂)
通用属性
示例:
// 网络图片
Image.network('https://example.com/pic.png', fit: BoxFit.cover)
// 本地 Assets(需在 pubspec.yaml 声明)
Image.asset('assets/images/logo.png')3.3 按钮(新版)重要更新
Flutter 3.x 已废弃 FlatButton、RaisedButton,统一使用新按钮。使用 styleFrom 快速定制。
TextButton:文字按钮(替代 FlatButton)
ElevatedButton:带阴影凸起按钮(替代 RaisedButton)
OutlinedButton:边框按钮(替代 OutlineButton)
共有属性
使用 styleFrom 快速定制
ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
foregroundColor: Colors.white, // 文字/图标颜色
backgroundColor: Colors.green, // 背景色
disabledForegroundColor: Colors.grey, // 禁用时文字颜色
disabledBackgroundColor: Colors.lightGrey,
elevation: 5, // 阴影高度
shadowColor: Colors.black54, // 阴影颜色
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
minimumSize: Size(120, 48), // 最小尺寸
tapTargetSize: MaterialTapTargetSize.shrinkWrap, // 点击区域大小
),
child: Text('按钮'),
)各按钮的默认差异
3.4 TextField:输入框
TextField 属性
InputDecoration 常用属性:
InputDecoration(
labelText: '用户名',
hintText: '请输入用户名',
prefixIcon: Icon(Icons.person),
suffixIcon: Icon(Icons.clear),
border: OutlineInputBorder(),
errorText: _hasError ? '用户名不能为空' : null,
)示例:
TextField(
decoration: InputDecoration(
labelText: '用户名',
hintText: '请输入用户名',
prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
),
onChanged: (value) => print(value),
)4. 交互与手势
Flutter 提供了 GestureDetector 来监听几乎所有手势,也可以直接使用带交互的组件。
GestureDetector 属性
注意: GestureDetector 可嵌套,事件会按需向上冒泡。若要阻止冒泡,使用 IgnorePointer。
GestureDetector(
onTap: () => print('点击了'),
onDoubleTap: () => print('双击了'),
onLongPress: () => print('长按了'),
child: Container(
color: Colors.amber,
width: 100,
height: 100,
child: Center(child: Text('点我')),
),
)5. 滚动组件:列表与网格
5.1 ListView:核心列表
ListView 的四种构造方式
常用属性(以 ListView.builder 为例)
示例:
ListView.builder(
itemCount: 100,
itemBuilder: (context, index) {
return ListTile(
leading: Icon(Icons.label),
title: Text('Item $index'),
);
},
)5.2 新特性:CarouselView(轮播图)
Flutter 3.24 新增的 Material 风格轮播组件。
CarouselView 属性
示例:
CarouselView(
itemExtent: 300,
children: [
Container(color: Colors.red, child: Center(child: Text('1'))),
Container(color: Colors.green, child: Center(child: Text('2'))),
Container(color: Colors.blue, child: Center(child: Text('3'))),
],
)5.3 Sliver:自定义滚动效果
Sliver 组件允许你创建自定义的滚动效果,如可伸缩的头部。Flutter 3.24 新增了 SliverFloatingHeader、PinnedHeaderSliver 等。
6. 主题与样式
6.1 Material 3 (M3)
Flutter 3.x 默认支持 Material 3,通过 useMaterial3: true 启用。
MaterialApp 中的主题配置
6.2 组件主题(新版写法)
Flutter 3.24 后,许多组件主题改为使用 *ThemeData 类(如 CardThemeData、ElevatedButtonThemeData),不再直接使用旧版 CardTheme 等。
ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.purple),
// 全局按钮样式
elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom(
minimumSize: Size(120, 48),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
),
// 全局卡片样式
cardTheme: CardThemeData(
elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
),
// 全局文本样式
textTheme: TextTheme(
displayLarge: TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
bodyMedium: TextStyle(fontSize: 14),
),
)7. 状态管理(进阶必学)
对于复杂应用,仅用 setState 会导致代码难以维护。推荐使用 Riverpod(目前最流行的方案)。
7.1 Riverpod 常用提供器
7.2 基本使用示例
// 1. 创建 Provider
final counterProvider = StateProvider<int>((ref) => 0);
// 2. 监听并修改
class HomePage extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final count = ref.watch(counterProvider);
return Scaffold(
body: Center(child: Text('$count')),
floatingActionButton: FloatingActionButton(
onPressed: () => ref.read(counterProvider.notifier).state++,
),
);
}
}ConsumerWidget 的 build 方法参数:
WidgetRef ref:用于读取提供器(ref.watch)或获取 notifier(ref.read)。
8. 实战:计数器应用(综合演练)
结合所学知识,我们不仅能做简单的加减法,还能加入“重置”和“限制负数”的逻辑。
import 'package:flutter/material.dart';
void main() => runApp(const MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
useMaterial3: true,
colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
),
home: const MyHomePage(title: 'Flutter 进阶计数器'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
void _decrementCounter() {
setState(() {
if (_counter > 0) _counter--;
});
}
void _resetCounter() {
setState(() {
_counter = 0;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('点击按钮改变数值:', style: TextStyle(fontSize: 18)),
Text(
'$_counter',
style: Theme.of(context).textTheme.displayMedium?.copyWith(
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(onPressed: _decrementCounter, child: const Text('-')),
const SizedBox(width: 20),
ElevatedButton(onPressed: _resetCounter, child: const Text('重置')),
const SizedBox(width: 20),
ElevatedButton(onPressed: _incrementCounter, child: const Text('+')),
],
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: '增加',
child: const Icon(Icons.add),
),
);
}
}