Widget 基础

Widget 是 Flutter 应用的构建块。理解 Widget 的概念和工作原理是掌握 Flutter 的关键。Flutter 3.28+ 提供了更多优化和新特性。

核心概念:在 Flutter 中,"一切皆 Widget"。从按钮到布局,从文本到动画,所有内容都是 Widget。

1. 什么是 Widget?

Widget 是 Flutter 中的核心概念,它们是:

  • UI 元素:按钮、文本、图片等
  • 布局组件:行、列、堆栈等
  • 功能组件:手势、主题、导航等
  • 不可变的:一旦创建就不能修改

2. Widget 类型

StatelessWidget(无状态 Widget)

无状态 Widget 是不可变的,一旦创建就不会改变。适用于静态内容。

import 'package:flutter/material.dart';

class MyTextWidget extends StatelessWidget {
  final String text;

  const MyTextWidget({super.key, required this.text});

  @override
  Widget build(BuildContext context) {
    return Text(
      text,
      style: const TextStyle(
        fontSize: 18,
        color: Colors.blue,
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: MyTextWidget(text: 'Hello, Widget!'),
        ),
      ),
    );
  }
}

StatefulWidget(有状态 Widget)

有状态 Widget 可以在其生命周期内改变状态。适用于需要动态更新的内容。

import 'package:flutter/material.dart';

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

  @override
  State createState() => _CounterWidgetState();
}

class _CounterWidgetState extends State {
  int _count = 0;

  void _increment() {
    setState(() {
      _count++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Text(
          '计数: $_count',
          style: const TextStyle(fontSize: 24),
        ),
        const SizedBox(height: 20),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('增加'),
        ),
      ],
    );
  }
}

3. 基础组件概览

以下是 Flutter 中最常用的基础组件,每个组件都有其特定的用途和特点。

📚 基础组件详解

📝 Text - 文本组件

Text 是最常用的组件之一,用于显示文本内容。支持丰富的样式定制,包括字体大小、颜色、字重、对齐方式等。

大标题文本
普通正文内容
小字注释说明
Text 组件渲染效果
Text(
  'Hello Flutter',
  style: TextStyle(
    fontSize: 24,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
  ),
)
🖼️ Image - 图片组件

Image 组件用于显示图片,支持多种来源:网络图片、本地资源、内存图片等。提供丰富的 fit 模式控制图片缩放。

cover
contain
fill
Image fit 模式展示
Image.network(
  'https://example.com/image.png',
  fit: BoxFit.cover,
  width: 200,
  height: 200,
)
⭐ Icon - 图标组件

Icon 组件用于显示 Material Design 图标,可以设置颜色、大小等属性。使用 Icons 类可以访问预定义的图标集。

🏠
❤️
⚙️
Icon 图标展示
Icon(
  Icons.favorite,
  color: Colors.red,
  size: 48,
)
📦 Container - 容器组件

Container 是一个多功能组合组件,可以设置内边距、外边距、装饰、约束等。是布局中最常用的组件之一。

带阴影
圆角卡片
Container 装饰效果
Container(
  padding: EdgeInsets.all(16),
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(8),
    boxShadow: [
      BoxShadow(
        color: Colors.black.withOpacity(0.2),
        blurRadius: 10,
      )
    ]
  ),
)
↔️ Padding - 间距组件

Padding 用于在子组件周围添加内边距。可以设置统一值,也可以分别设置四个方向的值。

padding
不对称
Padding 间距效果
Padding(
  padding: EdgeInsets.symmetric(
    horizontal: 16,
    vertical: 8
  ),
  child: Text('Hello'),
)
📏 SizedBox - 尺寸组件

SizedBox 用于设置子组件的固定尺寸,或作为空白占位符。常用于控制间距和布局。

60x40
固定尺寸
水平间距
垂直间距
SizedBox 尺寸效果
// 设置固定尺寸
SizedBox(
  width: 100,
  height: 50,
  child: Text('Box'),
)

// 作为间距
SizedBox(height: 16)

4. 常用基础 Widget(详细)

Container

Container 是一个多功能组合 Widget,可以包含子 Widget、设置内边距、外边距、装饰等。

Container(
  width: 200,
  height: 200,
  padding: const EdgeInsets.all(20),
  margin: const EdgeInsets.symmetric(horizontal: 10),
  decoration: BoxDecoration(
    color: Colors.blue,
    borderRadius: BorderRadius.circular(10),
    boxShadow: [
      BoxShadow(
        color: Colors.black.withOpacity(0.2),
        blurRadius: 10,
        spreadRadius: 5,
      ),
    ],
  ),
  child: const Center(
    child: Text(
      'Container',
      style: TextStyle(color: Colors.white, fontSize: 18),
    ),
  ),
)

Text

Text Widget 用于显示文本内容。

📐 Text 渲染效果

Hello Flutter!
const Text(
  'Hello, Flutter!',
  style: TextStyle(
    fontSize: 24,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
    letterSpacing: 1.5,
    wordSpacing: 2.0,
  ),
  textAlign: TextAlign.center,
)

📋 Text 核心属性

属性 类型 说明 常用值
style TextStyle 文本样式 TextStyle()
textAlign TextAlign 文本对齐方式 center, left, right
maxLines int 最大行数 1, 2, 3...
overflow TextOverflow 溢出处理 ellipsis, fade, clip
textDirection TextDirection 文本方向 ltr, rtl
softWrap bool 是否自动换行 true, false
strutStyle StrutStyle 段落样式 StrutStyle()

🎨 TextStyle 核心属性

属性 类型 说明 常用值
fontSize double 字体大小 14, 16, 18...
fontWeight FontWeight 字体粗细 bold, normal, w500
color Color 字体颜色 Colors.blue, Color(0xFF...)
letterSpacing double 字母间距 1.0, 1.5, 2.0...
wordSpacing double 单词间距 1.0, 2.0, 3.0...
height double 行高 1.0, 1.2, 1.5...
fontFamily String 字体族 Roboto, Arial...
decoration TextDecoration 文本装饰 underline, lineThrough...

Image

Image Widget 用于显示图片。

📐 Image 渲染效果

图片预览
// 从网络加载图片
Image.network(
  'https://example.com/image.jpg',
  width: 200,
  height: 200,
  fit: BoxFit.cover,
)

// 从资源加载图片
Image.asset('assets/images/logo.png')

// 从文件加载
Image.file(File('/path/to/image.jpg'))

📋 Image 核心属性

属性 类型 说明 常用值
width double 图片宽度 100, 200, 300...
height double 图片高度 100, 200, 300...
fit BoxFit 图片填充方式 cover, contain, fill...
color Color 图片颜色 Colors.blue, Colors.red...
alignment AlignmentGeometry 对齐方式 center, topLeft, bottomRight...
repeat ImageRepeat 图片重复方式 noRepeat, repeat, repeatX...
semanticLabel String 语义标签 "用户头像", "产品图片"...
filterQuality FilterQuality 图片质量 low, medium, high, none
opacity double 透明度 0.0-1.0

🎯 BoxFit 详解

说明 效果
fill 完全填充,不保持宽高比 可能变形
cover 保持宽高比,完全覆盖 可能裁剪
contain 保持宽高比,完整显示 可能留白
fitWidth 保持宽度,高度自适应 宽度对齐
fitHeight 保持高度,宽度自适应 高度对齐
none 不进行缩放 原始大小
scaleDown 缩小图片以适应容器 不放大

Icon

Icon Widget 显示图标。

📐 Icon 渲染效果

❤️ 🔔 ⚙️ 📷
const Icon(
  Icons.favorite,
  size: 48,
  color: Colors.red,
)

// 自定义颜色和大小
Icon(
  Icons.star,
  color: Colors.yellow,
  size: 32,
)

📋 Icon 核心属性

属性 类型 说明 常用值
icon IconData 图标数据 Icons.star, Icons.home...
size double 图标大小 16, 24, 32, 48...
color Color 图标颜色 Colors.blue, Colors.red...
semanticLabel String 语义标签 "收藏", "设置"...
textDirection TextDirection 文本方向 ltr, rtl
shadows List<Shadow> 阴影效果 [Shadow(blur: 10...)]
applyTextScaling bool 是否应用文本缩放 true, false
grade int 图标等级 0-255
weight int 图标权重 100-900
opticalSize int 光学尺寸 20-48
fill double 填充程度 0.0-1.0

🎨 常用图标集

图标集 说明 示例
Material Icons Material Design 官方图标 Icons.star, Icons.home
Cupertino Icons iOS 风格图标 CupertinoIcons.heart
Font Awesome Font Awesome 图标 FontAwesomeIcons.star
自定义图标 使用自定义字体文件 IconData(0xe800, fontFamily: 'MyFont')

4. 交互 Widget

按钮

Flutter 提供了多种按钮类型。

// ElevatedButton(Material 风格凸起按钮)
ElevatedButton(
  onPressed: () {
    print('ElevatedButton 被点击');
  },
  style: ElevatedButton.styleFrom(
    backgroundColor: Colors.blue,
    padding: const EdgeInsets.symmetric(
      horizontal: 20,
      vertical: 15,
    ),
  ),
  child: const Text('点击我'),
)

// TextButton(文本按钮)
TextButton(
  onPressed: () {},
  child: const Text('文本按钮'),
)

// OutlinedButton(轮廓按钮)
OutlinedButton(
  onPressed: () {},
  style: OutlinedButton.styleFrom(
    side: const BorderSide(color: Colors.blue),
  ),
  child: const Text('轮廓按钮'),
)

// IconButton(图标按钮)
IconButton(
  onPressed: () {},
  icon: const Icon(Icons.favorite),
  iconSize: 32,
  color: Colors.red,
)

TextField

TextField Widget 用于接收用户输入。

TextField(
  decoration: InputDecoration(
    labelText: '用户名',
    hintText: '请输入用户名',
    prefixIcon: const Icon(Icons.person),
    border: OutlineInputBorder(
      borderRadius: BorderRadius.circular(10),
    ),
    filled: true,
    fillColor: Colors.grey[100],
  ),
  onChanged: (value) {
    print('输入: $value');
  },
  onSubmitted: (value) {
    print('提交: $value');
  },
)

5. Widget 树

Flutter 应用的 UI 由 Widget 树组成。理解 Widget 树对于构建复杂 UI 至关重要。

MaterialApp
 └── Scaffold
     ├── AppBar
     │   └── Text('My App')
     ├── Body
     │   ├── Column
     │   │   ├── Text('Hello')
     │   │   └── Button('Click Me')
     │   └── Container
     └── FloatingActionButton

6. 生命周期

理解 StatefulWidget 的生命周期对于管理状态和资源很重要。

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

  @override
  State createState() => _LifecycleWidgetState();
}

class _LifecycleWidgetState extends State {
  @override
  void initState() {
    super.initState();
    print('initState: Widget 初始化');
    // 初始化操作,如加载数据
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('didChangeDependencies: 依赖变化');
    // 依赖项(如 Theme)变化时调用
  }

  @override
  void didUpdateWidget(LifecycleWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('didUpdateWidget: Widget 更新');
    // 父 Widget 重建时调用
  }

  @override
  void setState(VoidCallback fn) {
    super.setState(fn);
    print('setState: 状态更新');
  }

  @override
  void deactivate() {
    super.deactivate();
    print('deactivate: Widget 即将被移除');
  }

  @override
  void dispose() {
    super.dispose();
    print('dispose: Widget 被销毁');
    // 清理资源,如关闭流、取消订阅
  }

  @override
  Widget build(BuildContext context) {
    print('build: Widget 构建');
    return Container(
      child: const Text('生命周期示例'),
    );
  }
}

⏱️ StatefulWidget 生命周期时序图

Widget
State
1. 创建阶段
Widget 创建 → createState() → State 创建 → initState()
2. 构建阶段
didChangeDependencies() → build()
3. 更新阶段
父 Widget 更新 → didUpdateWidget() → setState() → build()
4. 销毁阶段
Widget 移除 → deactivate() → dispose()

📊 Widget 类型对比

StatelessWidget vs StatefulWidget 对比表
特性 StatelessWidget StatefulWidget
状态 不可变 可变
生命周期 简单(仅 build) 复杂(多个阶段)
性能 更好 较重
使用场景 静态内容 动态交互
状态管理 依赖父组件 自身管理

7. 最佳实践

  • 合理拆分 Widget:将大 Widget 拆分成小的、可重用的组件
  • 使用 const:对于不变的 Widget 使用 const 构造函数
  • 避免过度嵌套:使用私有方法或独立 Widget 减少嵌套层级
  • 选择合适的状态管理:根据应用复杂度选择 setState、Provider、Bloc 等
  • 使用 Keys:在需要控制 Widget 身份时使用 Key
提示:使用 Flutter DevTools 可以帮助可视化 Widget 树和调试 Widget 性能。
注意:频繁调用 setState 可能会影响性能。在构建复杂 Widget 树时,考虑将可变部分提取为独立的 Widget。