现在位置: 首页 > Flutter 教程 > 正文

Flutter Widget 基础

Widget 是 Flutter UI 的基本构建块。

在 Flutter 中,一切皆为 Widget,从简单的文本到复杂的页面布局都是由 Widget 组合而成的。


什么是 Widget?

Widget 是描述 UI 外观和行为的 Dart 类。每个 Flutter 应用本质上就是由 Widget 组成的树形结构,称为 Widget 树。

实例:最简单的 Widget 示例

import 'package:flutter/material.dart';

// 定义一个简单的 Widget
class HelloWidget extends StatelessWidget {
  const HelloWidget({super.key});

  @override
  Widget build(BuildContext context) {
    // 返回一个 Text Widget,显示 "Hello World"
    return const Text('Hello World');
  }
}

StatelessWidget - 无状态组件

StatelessWidget 是不可变的 Widget,一旦创建,其属性就不能更改。适用于显示静态内容的场景,如文本、图片、图标等。

基本结构

实例:StatelessWidget 示例

import 'package:flutter/material.dart';

// 定义无状态组件
class MyTextWidget extends StatelessWidget {
  // 构造函数参数(不可变属性)
  final String text;
  final Color textColor;
  final double fontSize;

  // 使用 const 构造函数
  const MyTextWidget({
    super.key,
    required this.text,
    this.textColor = Colors.black,
    this.fontSize = 16.0,
  });

  @override
  Widget build(BuildContext context) {
    // build 方法返回另一个 Widget
    return Text(
      text,
      style: TextStyle(
        color: textColor,
        fontSize: fontSize,
      ),
    );
  }
}

// 使用示例
// MyTextWidget(text: 'Hello', textColor: Colors.red)

适用场景

  • 静态文本展示
  • 图片显示
  • 图标展示
  • 不随时间变化的布局

StatefulWidget - 有状态组件

StatefulWidget 是可变的 Widget,可以随着内部数据变化而更新 UI。适用于需要响应用户交互或数据变化的场景。

基本结构

实例:StatefulWidget 示例

import 'package:flutter/material.dart';

// 定义有状态组件
class CounterWidget extends StatefulWidget {
  const CounterWidget({super.key});

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

// State 类持有可变状态
class _CounterWidgetState extends State<CounterWidget> {
  // 计数器状态
  int _count = 0;

  // 增加计数器的方法
  void _increment() {
    // 调用 setState 通知框架状态已更改
    setState(() {
      _count++;
    });
  }

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

setState 方法

在 StatefulWidget 中,如果状态发生变化,必须调用 setState 方法来通知 Flutter 重新构建 UI。

如果修改了状态但没有调用 setState,UI 不会更新。这是因为 Flutter 通过 setState 来判断是否需要重新构建 Widget。

适用场景

  • 计数器、计时器等动态数据
  • 表单输入
  • 列表项的增删改
  • 用户交互响应

build 方法

每个 Widget 都必须实现 build 方法,该方法返回 Widget 树的一部分。

基本规则

规则说明
返回值必须返回一个 Widget,不能返回 null
参数接收 BuildContext 参数,表示在 Widget 树中的位置
调用时机首次构建、父 Widget 重建、状态变化时

实例:build 方法示例

@override
Widget build(BuildContext context) {
  // BuildContext 提供了访问主题、主题等信息的能力
  // 例如获取当前主题颜色
  final theme = Theme.of(context);

  // 返回一个 Widget
  return Container(
    padding: const EdgeInsets.all(16.0),
    decoration: BoxDecoration(
      color: theme.colorScheme.primaryContainer,
      borderRadius: BorderRadius.circular(8),
    ),
    child: Text(
      'Hello Flutter',
      style: TextStyle(
        color: theme.colorScheme.onPrimaryContainer,
        fontSize: 20,
      ),
    ),
  );
}

常用基础 Widget

Text - 文本显示

实例:Text Widget

// 基本文本
const Text('Hello World')

// 带样式的文本
Text(
  'Hello Flutter',
  style: TextStyle(
    fontSize: 20,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
  ),
)

// 带有可选样式的文本
Text.rich(
  TextSpan(
    text: 'Hello ',
    children: [
      TextSpan(
        text: 'Flutter',
        style: TextStyle(fontWeight: FontWeight.bold),
      ),
    ],
  ),
)

Icon - 图标

实例:Icon Widget

// 使用 Material Icons
const Icon(Icons.home)              // 主页图标
const Icon(Icons.star, color: Colors.yellow)  // 带颜色的星星
const Icon(Icons.settings, size: 48)  // 大小为 48 的设置图标

Image - 图片

实例:Image Widget

// 从网络加载图片
Image.network('https://example.com/image.png')

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

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

// 带参数的图片
Image.network(
  'https://example.com/image.png',
  width: 200,
  height: 200,
  fit: BoxFit.cover,
)

Button - 按钮

实例:按钮 Widget

// 文字按钮
TextButton(
  onPressed: () { /* 处理点击 */ },
  child: const Text('文字按钮'),
)

// 悬浮按钮
FloatingActionButton(
  onPressed: () { /* 处理点击 */ },
  child: const Icon(Icons.add),
)

//  ElevatedButton - 带阴影的按钮
ElevatedButton(
  onPressed: () { /* 处理点击 */ },
  child: const Text('提交'),
)

// 带图标的按钮
ElevatedButton.icon(
  onPressed: () { /* 处理点击 */ },
  icon: const Icon(Icons.save),
  label: const Text('保存'),
)

Widget 组合

Flutter 的强大之处在于可以组合 Widget。通过嵌套,一个简单的 Widget 可以构建出复杂的 UI。

实例:组合 Widget

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

  @override
  Widget build(BuildContext context) {
    return Card(
      // Card 是 Material Design 的卡片组件
      elevation: 4,  // 阴影深度
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            // 标题
            const Text(
              '卡片标题',
              style: TextStyle(
                fontSize: 20,
                fontWeight: FontWeight.bold,
              ),
            ),
            const SizedBox(height: 8),
            // 描述文本
            const Text(
              '这是卡片的描述内容,可以包含多行文字。',
            ),
            const SizedBox(height: 16),
            // 按钮行
            Row(
              mainAxisAlignment: MainAxisAlignment.end,
              children: [
                TextButton(
                  onPressed: () {},
                  child: const Text('取消'),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () {},
                  child: const Text('确认'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}