2. 使用StatelessWidget构建静态个人名片页面
StatelessWidget 与 Widget 树:名片页面的结构拆解
静态名片页面的本质是一棵由 StatelessWidget 组合而成的 Widget 树。根节点是自定义的 BusinessCard,它不持有任何可变状态,只负责把 Scaffold、Column、CircleAvatar、Text、Icon 等基础组件按层级拼装起来。理解这棵树,比记住每个组件的构造参数更重要。
从零构建名片页面
新建 lib/main.dart,入口 runApp 直接挂载 BusinessCard。整个页面只有一个自定义 Widget,其余全部由 Flutter 内置组件组合完成。
import 'package:flutter/material.dart';
void main() => runApp(const MaterialApp(
debugShowCheckedModeBanner: false,
home: BusinessCard(),
));
class BusinessCard extends StatelessWidget {
const BusinessCard({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('个人名片'),
centerTitle: true,
backgroundColor: Colors.blue.shade700,
foregroundColor: Colors.white,
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const CircleAvatar(
radius: 50,
backgroundImage: NetworkImage('https://i.pravatar.cc/150?img=12'),
),
const SizedBox(height: 20),
const Text(
'张明',
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold),
),
const SizedBox(height: 8),
const Text(
'Flutter 开发工程师',
style: TextStyle(fontSize: 16, color: Colors.grey),
),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.email, size: 18, color: Colors.blueGrey),
SizedBox(width: 6),
Text('zhangming@example.com',
style: TextStyle(fontSize: 14)),
],
),
const SizedBox(height: 10),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Icon(Icons.phone, size: 18, color: Colors.blueGrey),
SizedBox(width: 6),
Text('+86 138-0000-1234',
style: TextStyle(fontSize: 14)),
],
),
],
),
),
);
}
}
Widget 树与渲染的对应关系
上面代码中,Column 的 children 列表顺序决定了垂直排列顺序:头像 → 姓名 → 职位 → 邮箱行 → 电话行。SizedBox 作为间距占位符,本身不绘制任何内容,只参与布局计算。每个 Row 内部用 mainAxisAlignment: center 让图标与文字水平居中。
| Widget | 作用 | 关键参数 |
|---|---|---|
Scaffold | 提供页面骨架与 AppBar | appBar、body |
CircleAvatar | 圆形头像容器 | radius、backgroundImage |
Text | 展示姓名、职位、联系方式 | style.fontSize、fontWeight |
Row | 图标与文字水平排列 | mainAxisAlignment |
SizedBox | 控制元素间距 | height、width |
头像使用
NetworkImage 需要网络权限;若在模拟器或真机上图片不显示,可换成本地 AssetImage 并配置 pubspec.yaml 的 assets 路径。验证与观察要点
- 运行后确认 AppBar 标题居中、头像为圆形、姓名加粗且字号明显大于职位。
- 热重载(
r)修改任意Text内容,界面立即更新,说明 StatelessWidget 在输入变化时整体重建。 - 尝试在
build中调用setState,编译器会报错——这是 StatelessWidget 的硬性约束。 - 把
Column换成ListView,观察布局行为差异,理解“无状态”不等于“不能滚动”。
不要在 StatelessWidget 中保存需要跨帧保持的数据(如计数器、输入框内容)。这类需求应交给 StatefulWidget,否则每次重建都会丢失。