logo
Flutter 入门

Flutter Widget 基础

简介

深入理解 Flutter 的核心概念 - Widget,掌握常用的 Widget 类型和使用方法

什么是 Widget?

Widget 是 Flutter 中构建用户界面的基本单位。在 Flutter 中,一切皆为 Widget,从一个简单的按钮到整个应用程序,都是由 Widget 组成的。Widget 描述了在当前配置和状态下视图应该呈现的样子。

Widget 的特点

  • 不可变性:Widget 是不可变的,每次更新都会创建新的 Widget 实例
  • 组合性:复杂的 Widget 可以由简单的 Widget 组合而成
  • 层次结构:Widget 以树形结构组织,形成 Widget 树

Widget 的分类

1. StatelessWidget(无状态组件)

适用于界面内容固定,不需要动态更新的场景。

class WelcomeMessage extends StatelessWidget {
  final String name;

  const WelcomeMessage({Key? key, required this.name}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Text('Welcome, $name!');
  }
}

2. StatefulWidget(有状态组件)

适用于需要动态更新界面内容的场景。

class Counter extends StatefulWidget {
  const Counter({Key? key}) : super(key: key);

  @override
  _CounterState createState() => _CounterState();
}

class _CounterState extends State<Counter> {
  int _count = 0;

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

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text('Count: $_count'),
        ElevatedButton(
          onPressed: _increment,
          child: const Text('Increment'),
        ),
      ],
    );
  }
}

常用的基础 Widget

1. 布局 Widget

// 线性布局
Row(  // 水平排列
  children: [
    Icon(Icons.star),
    Text('Rating: 4.5'),
  ],
)

Column(  // 垂直排列
  children: [
    Text('Title'),
    Text('Subtitle'),
  ],
)

// 弹性布局
Flex(
  direction: Axis.horizontal,
  children: [
    Expanded(
      flex: 2,  // 占用 2/3 空间
      child: Container(color: Colors.red),
    ),
    Expanded(
      flex: 1,  // 占用 1/3 空间
      child: Container(color: Colors.blue),
    ),
  ],
)

// 堆叠布局
Stack(
  children: [
    Image.asset('background.png'),
    Positioned(
      bottom: 10,
      right: 10,
      child: Text('Overlay Text'),
    ),
  ],
)

2. 容器 Widget

// 基础容器
Container(
  margin: EdgeInsets.all(8.0),
  padding: EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
  decoration: BoxDecoration(
    color: Colors.white,
    borderRadius: BorderRadius.circular(8.0),
    boxShadow: [
      BoxShadow(
        color: Colors.grey.withOpacity(0.5),
        spreadRadius: 2,
        blurRadius: 5,
        offset: Offset(0, 3),
      ),
    ],
  ),
  child: Text('Hello Flutter!'),
)

// 卡片容器
Card(
  child: ListTile(
    leading: Icon(Icons.album),
    title: Text('Album Title'),
    subtitle: Text('Artist Name'),
    trailing: Icon(Icons.more_vert),
  ),
)

3. 基础组件

// 文本
Text(
  'Hello Flutter!',
  style: TextStyle(
    fontSize: 24.0,
    fontWeight: FontWeight.bold,
    color: Colors.blue,
  ),
)

// 图片
Image.network(
  'https://example.com/image.jpg',
  width: 200,
  height: 200,
  fit: BoxFit.cover,
)

// 按钮
ElevatedButton(
  onPressed: () {
    print('Button pressed!');
  },
  child: Text('Click Me'),
)

TextButton(
  onPressed: () {
    print('Text button pressed!');
  },
  child: Text('Text Button'),
)

IconButton(
  onPressed: () {
    print('Icon button pressed!');
  },
  icon: Icon(Icons.favorite),
)

Widget 生命周期

对于 StatefulWidget,其生命周期包括以下阶段:

  1. createState():创建 State 对象
  2. initState():State 对象初始化
  3. didChangeDependencies():依赖变化时调用
  4. build():构建 Widget
  5. didUpdateWidget():Widget 配置更新时调用
  6. setState():状态更新时调用
  7. dispose():Widget 销毁时调用
class LifecycleWidget extends StatefulWidget {
  const LifecycleWidget({Key? key}) : super(key: key);

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

class _LifecycleWidgetState extends State<LifecycleWidget> {
  @override
  void initState() {
    super.initState();
    print('1. initState called');
  }

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    print('2. didChangeDependencies called');
  }

  @override
  Widget build(BuildContext context) {
    print('3. build called');
    return Container(
      child: Text('Lifecycle Demo'),
    );
  }

  @override
  void didUpdateWidget(covariant LifecycleWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    print('4. didUpdateWidget called');
  }

  @override
  void dispose() {
    print('5. dispose called');
    super.dispose();
  }
}

实践:创建一个简单的计数器应用

结合所学的 Widget 知识,创建一个完整的计数器应用:

import 'package:flutter/material.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            const Text(
              'You have pushed the button this many times:',
            ),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: _incrementCounter,
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}

下一步

掌握了 Widget 的基础知识后,我们将在下一章学习 Flutter 的状态管理,包括 setState、Provider、Riverpod 等不同的状态管理方案。