<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Telus</title><description>Solution &amp; Thinking</description><link>https://zgq1008.github.io/</link><language>zh_CN</language><item><title>Flutter Day02: Image 与 TextField 组件</title><link>https://zgq1008.github.io/posts/flutter/flutter_day02/</link><guid isPermaLink="true">https://zgq1008.github.io/posts/flutter/flutter_day02/</guid><description>记录 Flutter 图片加载和输入组件的常用属性与实践示例。</description><pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Flutter Day02: Image 与 TextField 组件&lt;/h1&gt;
&lt;p&gt;本文整理 Flutter 中常用的图片组件 &lt;code&gt;Image&lt;/code&gt; 和输入组件 &lt;code&gt;TextField&lt;/code&gt;，包含核心属性与实用示例。&lt;/p&gt;
&lt;h2&gt;1. Image 组件详解&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Image&lt;/code&gt; 用于从不同来源（网络、本地资源、文件系统、内存）加载并显示图片。&lt;/p&gt;
&lt;h3&gt;1.1 常见构造函数（图片来源）&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;构造函数&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Image.asset()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;从项目资源目录（在 &lt;code&gt;pubspec.yaml&lt;/code&gt; 中配置）加载图片&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Image.asset(&apos;assets/images/logo.png&apos;)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Image.network()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;从网络 URL 加载图片，支持缓存&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Image.network(&apos;https://picsum.photos/300/200&apos;)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Image.file()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;从设备本地文件系统加载图片&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Image.file(File(&apos;/path/to/image.png&apos;))&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Image.memory()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;从内存字节数组 &lt;code&gt;Uint8List&lt;/code&gt; 加载图片&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Image.memory(bytes)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;1.2 核心属性&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;常见值/建议&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制图片如何适应容器（最重要）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BoxFit.cover&lt;/code&gt;（常用）、&lt;code&gt;contain&lt;/code&gt;、&lt;code&gt;fill&lt;/code&gt;、&lt;code&gt;fitWidth&lt;/code&gt;、&lt;code&gt;fitHeight&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;width&lt;/code&gt; / &lt;code&gt;height&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;图片显示宽高（逻辑像素）&lt;/td&gt;
&lt;td&gt;如 &lt;code&gt;width: 120, height: 120&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alignment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;图片在容器内对齐方式&lt;/td&gt;
&lt;td&gt;默认 &lt;code&gt;Alignment.center&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;color&lt;/code&gt; + &lt;code&gt;colorBlendMode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;给图片着色&lt;/td&gt;
&lt;td&gt;常用于单色图标或蒙层效果&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;repeat&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;图片小于容器时平铺&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ImageRepeat.repeat&lt;/code&gt;、&lt;code&gt;repeatX&lt;/code&gt;、&lt;code&gt;repeatY&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;frameBuilder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;自定义加载过程（如渐显）&lt;/td&gt;
&lt;td&gt;可配合动画提高体验&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;1.3 &lt;code&gt;fit&lt;/code&gt; 快速理解&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;BoxFit.cover&lt;/code&gt;: 等比缩放并填满容器，可能裁剪。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BoxFit.contain&lt;/code&gt;: 等比缩放完整显示，可能留白。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BoxFit.fill&lt;/code&gt;: 强制填满，可能拉伸变形。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BoxFit.fitWidth&lt;/code&gt;: 宽度撑满，高度等比缩放。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;BoxFit.fitHeight&lt;/code&gt;: 高度撑满，宽度等比缩放。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.4 示例: 常见图片加载与占位&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import &apos;dart:typed_data&apos;;
import &apos;package:flutter/material.dart&apos;;

class ImageDemoPage extends StatelessWidget {
	const ImageDemoPage({super.key, required this.memoryBytes});

	final Uint8List memoryBytes;

	@override
	Widget build(BuildContext context) {
		return Scaffold(
			appBar: AppBar(title: const Text(&apos;Image Demo&apos;)),
			body: ListView(
				padding: const EdgeInsets.all(16),
				children: [
					const Text(&apos;1) Asset 图片&apos;),
					Image.asset(
						&apos;assets/images/logo.png&apos;,
						height: 120,
						fit: BoxFit.contain,
					),
					const SizedBox(height: 16),

					const Text(&apos;2) 网络图片（带加载中提示和错误兜底）&apos;),
					Image.network(
						&apos;https://picsum.photos/400/200&apos;,
						height: 120,
						fit: BoxFit.cover,
						loadingBuilder: (context, child, progress) {
							if (progress == null) return child;
							return const SizedBox(
								height: 120,
								child: Center(child: CircularProgressIndicator()),
							);
						},
						errorBuilder: (context, error, stackTrace) =&amp;gt; const SizedBox(
							height: 120,
							child: Center(child: Text(&apos;图片加载失败&apos;)),
						),
					),
					const SizedBox(height: 16),

					const Text(&apos;3) 内存图片&apos;),
					Image.memory(
						memoryBytes,
						height: 120,
						fit: BoxFit.cover,
					),
				],
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;1.5 实战建议&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;网络图片尽量加 &lt;code&gt;loadingBuilder&lt;/code&gt; 和 &lt;code&gt;errorBuilder&lt;/code&gt;，避免白屏。&lt;/li&gt;
&lt;li&gt;头像、卡片封面常用 &lt;code&gt;BoxFit.cover&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;需要渐显效果可使用 &lt;code&gt;FadeInImage&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Flutter 默认有内存缓存；需要磁盘持久化缓存可用 &lt;code&gt;cached_network_image&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;2. TextField 组件详解&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;TextField&lt;/code&gt; 是 Material Design 的文本输入框，支持丰富装饰、输入控制和事件回调。&lt;/p&gt;
&lt;h3&gt;2.1 核心属性&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;示例 / 备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;controller&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;绑定 &lt;code&gt;TextEditingController&lt;/code&gt;，用于读写文本&lt;/td&gt;
&lt;td&gt;大多数业务场景必备&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;decoration&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;输入框外观配置&lt;/td&gt;
&lt;td&gt;&lt;code&gt;InputDecoration(...)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;keyboardType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;键盘类型&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TextInputType.emailAddress&lt;/code&gt;、&lt;code&gt;number&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;textInputAction&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;键盘右下角动作按钮&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TextInputAction.search&lt;/code&gt;、&lt;code&gt;done&lt;/code&gt;、&lt;code&gt;next&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;obscureText&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;是否隐藏输入内容&lt;/td&gt;
&lt;td&gt;密码输入设为 &lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;onChanged&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文本变化回调&lt;/td&gt;
&lt;td&gt;实时搜索、校验&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;onSubmitted&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;点击动作按钮回调&lt;/td&gt;
&lt;td&gt;提交表单、搜索&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2.2 InputDecoration 常见字段&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;labelText&lt;/code&gt;: 浮动标签。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;hintText&lt;/code&gt;: 占位提示。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border&lt;/code&gt;: 边框样式（如 &lt;code&gt;OutlineInputBorder()&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;prefixIcon&lt;/code&gt; / &lt;code&gt;suffixIcon&lt;/code&gt;: 前后图标。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;errorText&lt;/code&gt;: 错误提示（非 &lt;code&gt;null&lt;/code&gt; 时边框变红）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.3 示例: 登录表单（含焦点切换与基础校验）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import &apos;package:flutter/material.dart&apos;;

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

	@override
	State&amp;lt;LoginFormPage&amp;gt; createState() =&amp;gt; _LoginFormPageState();
}

class _LoginFormPageState extends State&amp;lt;LoginFormPage&amp;gt; {
	final _emailController = TextEditingController();
	final _passwordController = TextEditingController();
	final _passwordFocus = FocusNode();

	String? _emailError;
	String? _passwordError;

	@override
	void dispose() {
		_emailController.dispose();
		_passwordController.dispose();
		_passwordFocus.dispose();
		super.dispose();
	}

	void _submit() {
		final email = _emailController.text.trim();
		final password = _passwordController.text;

		setState(() {
			_emailError = email.contains(&apos;@&apos;) ? null : &apos;请输入正确的邮箱&apos;;
			_passwordError = password.length &amp;gt;= 6 ? null : &apos;密码至少 6 位&apos;;
		});

		if (_emailError == null &amp;amp;&amp;amp; _passwordError == null) {
			ScaffoldMessenger.of(context).showSnackBar(
				const SnackBar(content: Text(&apos;登录请求已提交&apos;)),
			);
		}
	}

	@override
	Widget build(BuildContext context) {
		return Scaffold(
			appBar: AppBar(title: const Text(&apos;TextField Demo&apos;)),
			body: Padding(
				padding: const EdgeInsets.all(16),
				child: Column(
					children: [
						TextField(
							controller: _emailController,
							keyboardType: TextInputType.emailAddress,
							textInputAction: TextInputAction.next,
							onSubmitted: (_) =&amp;gt; _passwordFocus.requestFocus(),
							decoration: InputDecoration(
								labelText: &apos;邮箱&apos;,
								hintText: &apos;请输入邮箱地址&apos;,
								prefixIcon: const Icon(Icons.email_outlined),
								border: const OutlineInputBorder(),
								errorText: _emailError,
							),
						),
						const SizedBox(height: 12),
						TextField(
							controller: _passwordController,
							focusNode: _passwordFocus,
							obscureText: true,
							textInputAction: TextInputAction.done,
							onSubmitted: (_) =&amp;gt; _submit(),
							decoration: InputDecoration(
								labelText: &apos;密码&apos;,
								hintText: &apos;请输入密码&apos;,
								prefixIcon: const Icon(Icons.lock_outline),
								border: const OutlineInputBorder(),
								errorText: _passwordError,
							),
						),
						const SizedBox(height: 16),
						SizedBox(
							width: double.infinity,
							child: FilledButton(
								onPressed: _submit,
								child: const Text(&apos;登录&apos;),
							),
						),
					],
				),
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.4 实战建议&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;优先使用 &lt;code&gt;TextEditingController&lt;/code&gt; 获取输入值。&lt;/li&gt;
&lt;li&gt;在 &lt;code&gt;StatefulWidget&lt;/code&gt; 中记得 &lt;code&gt;dispose()&lt;/code&gt; 控制器和 &lt;code&gt;FocusNode&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;表单较复杂时建议配合 &lt;code&gt;Form&lt;/code&gt; + &lt;code&gt;TextFormField&lt;/code&gt; + &lt;code&gt;validator&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;搜索框可用 &lt;code&gt;onChanged&lt;/code&gt;，提交行为可用 &lt;code&gt;onSubmitted&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Flutter Day03: 常用滚动组件</title><link>https://zgq1008.github.io/posts/flutter/flutter_day03/</link><guid isPermaLink="true">https://zgq1008.github.io/posts/flutter/flutter_day03/</guid><description>SingleChildScrollView、ListView 等滚动组件使用场景与注意点整理。</description><pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Flutter Day03 - 常用滚动组件笔记&lt;/h1&gt;
&lt;h2&gt;1. SingleChildScrollView&lt;/h2&gt;
&lt;h3&gt;1.1 组件作用&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;让单个子组件具备滚动能力。&lt;/li&gt;
&lt;li&gt;常见搭配是 &lt;code&gt;Column&lt;/code&gt;，用于承载一组内容块。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.2 适用场景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;长表单。&lt;/li&gt;
&lt;li&gt;设置页。&lt;/li&gt;
&lt;li&gt;内容总量不大但高度不固定的页面。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.3 特点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;子节点会一次性渲染完成。&lt;/li&gt;
&lt;li&gt;代码简单，适合中小体量内容。&lt;/li&gt;
&lt;li&gt;数据量很大时性能不如 &lt;code&gt;ListView.builder&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.4 代码引用（你的示例）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;import &apos;package:flutter/material.dart&apos;;

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

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

	@override
	State&amp;lt;MySingleChildScrollView&amp;gt; createState() =&amp;gt;
			_MySingleChildScrollViewState();
}

class _MySingleChildScrollViewState extends State&amp;lt;MySingleChildScrollView&amp;gt; {
	ScrollController _scrollController = ScrollController();

	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			home: Scaffold(
				appBar: AppBar(title: const Text(&apos;SingleChildScrollView&apos;)),
				body: Stack(
					children: [
						SingleChildScrollView(
							controller: _scrollController,
							padding: const EdgeInsets.all(20),
							child: Column(
								children: List.generate(100, (index) {
									return Container(
										margin: const EdgeInsets.only(top: 10),
										alignment: Alignment.center,
										width: double.infinity,
										height: 100,
										color: Colors.blue,
										child: Text(
											&quot;Item $index&quot;,
											style: const TextStyle(color: Colors.white, fontSize: 20),
										),
									);
								}),
							),
						),
						Positioned(
							bottom: 20,
							right: 20,
							child: GestureDetector(
								onTap: () {
									_scrollController.animateTo(
										_scrollController.position.maxScrollExtent,
										duration: const Duration(seconds: 1),
										curve: Curves.easeInOut,
									);
								},
								child: Container(
									height: 80,
									width: 80,
									decoration: BoxDecoration(
										color: Colors.red,
										borderRadius: BorderRadius.circular(40),
									),
									alignment: Alignment.center,
									child: const Text(
										&quot;跳转底部&quot;,
										style: TextStyle(color: Colors.white, fontSize: 16),
									),
								),
							),
						),
						Positioned(
							top: 20,
							right: 20,
							child: GestureDetector(
								onTap: () {
									_scrollController.animateTo(
										_scrollController.position.minScrollExtent,
										duration: const Duration(seconds: 1),
										curve: Curves.easeInOut,
									);
								},
								child: Container(
									height: 80,
									width: 80,
									decoration: BoxDecoration(
										color: Colors.red,
										borderRadius: BorderRadius.circular(40),
									),
									alignment: Alignment.center,
									child: const Text(
										&quot;跳转顶部&quot;,
										style: TextStyle(color: Colors.white, fontSize: 16),
									),
								),
							),
						),
					],
				),
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;1.5 关键点总结&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ScrollController&lt;/code&gt; 可控制滚动位置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;animateTo&lt;/code&gt; 有动画，&lt;code&gt;jumpTo&lt;/code&gt; 无动画。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Stack + Positioned&lt;/code&gt; 可以叠加悬浮按钮（顶部/底部跳转）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1.6 常用属性知识点及应用&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;常见应用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;controller&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;绑定滚动控制器&lt;/td&gt;
&lt;td&gt;点击按钮回到顶部/底部、监听滚动位置&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scrollDirection&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;滚动方向，默认纵向&lt;/td&gt;
&lt;td&gt;横向图片流可设置为 &lt;code&gt;Axis.horizontal&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;reverse&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;是否反向滚动&lt;/td&gt;
&lt;td&gt;聊天列表需要从底部开始时可用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;padding&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;内容内边距&lt;/td&gt;
&lt;td&gt;页面留白、避免内容贴边&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;physics&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;滚动行为&lt;/td&gt;
&lt;td&gt;使用 &lt;code&gt;BouncingScrollPhysics&lt;/code&gt; 实现 iOS 弹性效果&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;child&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;单个子组件&lt;/td&gt;
&lt;td&gt;通常放 &lt;code&gt;Column&lt;/code&gt;、&lt;code&gt;Form&lt;/code&gt; 等组合内容&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;应用示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;SingleChildScrollView(
	controller: _scrollController,
	scrollDirection: Axis.vertical,
	padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
	physics: const BouncingScrollPhysics(),
	child: Column(
		children: const [
			Text(&apos;表单标题&apos;),
			SizedBox(height: 12),
			Text(&apos;更多内容...&apos;),
		],
	),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;2. ListView.builder&lt;/h2&gt;
&lt;h3&gt;2.1 组件作用&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;构建长列表。&lt;/li&gt;
&lt;li&gt;按需渲染可见区域的 item，提高性能。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.2 适用场景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;数据量较大列表。&lt;/li&gt;
&lt;li&gt;列表项结构基本一致。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.3 代码引用（你的示例）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class MyListView1 extends StatefulWidget {
	const MyListView1({super.key});

	@override
	State&amp;lt;MyListView1&amp;gt; createState() =&amp;gt; _MyListViewState1();
}

class _MyListViewState1 extends State&amp;lt;MyListView1&amp;gt; {
	ScrollController _scrollController = ScrollController();

	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			home: Scaffold(
				appBar: AppBar(title: const Text(&quot;ListView.builder&quot;)),
				body: ListView.builder(
					itemCount: 100,
					itemBuilder: (BuildContext context, int index) {
						return Container(
							margin: EdgeInsets.only(top: 10),
							alignment: Alignment.center,
							width: double.infinity,
							height: 100,
							color: Colors.blue,
							child: Text(
								&quot;Item $index&quot;,
								style: TextStyle(color: Colors.white, fontSize: 20),
							),
						);
					},
					padding: EdgeInsets.all(20),
				),
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2.4 关键参数&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;itemCount&lt;/code&gt;: 列表总项数。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;itemBuilder&lt;/code&gt;: 按索引构建每一项。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;padding&lt;/code&gt;: 列表内边距。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2.5 常用属性知识点及应用&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;常见应用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;itemCount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;列表项数量&lt;/td&gt;
&lt;td&gt;避免无限构建，明确数据边界&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;itemBuilder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;按索引构建 item&lt;/td&gt;
&lt;td&gt;大列表按需渲染，减少内存占用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;controller&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;列表滚动控制器&lt;/td&gt;
&lt;td&gt;上拉分页、回到顶部、读取偏移量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scrollDirection&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;滚动方向&lt;/td&gt;
&lt;td&gt;横向商品卡片列表&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;padding&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;列表留白&lt;/td&gt;
&lt;td&gt;内容布局更美观&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;physics&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;滚动物理效果&lt;/td&gt;
&lt;td&gt;禁止滚动可用 &lt;code&gt;NeverScrollableScrollPhysics&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;shrinkWrap&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;按内容收缩尺寸&lt;/td&gt;
&lt;td&gt;嵌套在 &lt;code&gt;Column&lt;/code&gt; 时常用（注意性能）&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;应用示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ListView.builder(
	controller: _scrollController,
	itemCount: 100,
	padding: const EdgeInsets.all(16),
	physics: const AlwaysScrollableScrollPhysics(),
	itemBuilder: (context, index) {
		return ListTile(
			title: Text(&apos;Item $index&apos;),
		);
	},
)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;3. ListView.separated&lt;/h2&gt;
&lt;h3&gt;3.1 组件作用&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;与 &lt;code&gt;ListView.builder&lt;/code&gt; 一样按需渲染。&lt;/li&gt;
&lt;li&gt;额外提供分割线构建函数。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3.2 适用场景&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;需要明确区分 item 与 item 的列表。&lt;/li&gt;
&lt;li&gt;例如：订单列表、消息列表、设置分组项。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3.3 代码引用（你的示例）&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class MyListView2 extends StatefulWidget {
	const MyListView2({super.key});

	@override
	State&amp;lt;MyListView2&amp;gt; createState() =&amp;gt; _MyListViewState2();
}

class _MyListViewState2 extends State&amp;lt;MyListView2&amp;gt; {
	ScrollController _scrollController = ScrollController();

	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			home: Scaffold(
				appBar: AppBar(title: const Text(&quot;ListView.separated&quot;)),
				body: ListView.separated(
					itemCount: 100,
					itemBuilder: (BuildContext context, int index) {
						return Container(
							alignment: Alignment.center,
							width: double.infinity,
							height: 100,
							color: Colors.blue,
							child: Text(
								&quot;Item $index&quot;,
								style: TextStyle(color: Colors.white, fontSize: 20),
							),
						);
					},
					separatorBuilder: (BuildContext context, int index) {
						return Container(
							height: 1,
							color: Colors.grey,
						);
					},
					padding: EdgeInsets.all(20),
				),
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3.4 关键参数&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;itemBuilder&lt;/code&gt;: 构建列表项。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;separatorBuilder&lt;/code&gt;: 构建分割线。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;itemCount&lt;/code&gt;: 列表项数量。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3.5 常用属性知识点及应用&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;th&gt;常见应用&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;itemCount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;item 数量&lt;/td&gt;
&lt;td&gt;与后端数据长度保持一致&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;itemBuilder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;构建每个列表项&lt;/td&gt;
&lt;td&gt;渲染消息、订单、评论等结构化数据&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;separatorBuilder&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;构建分割区域&lt;/td&gt;
&lt;td&gt;分割线、分组间距、时间分隔条&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;controller&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;滚动控制&lt;/td&gt;
&lt;td&gt;无限加载、回滚定位&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;padding&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;列表内边距&lt;/td&gt;
&lt;td&gt;统一页面边距规范&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;physics&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;滚动行为控制&lt;/td&gt;
&lt;td&gt;嵌套滚动时配置更稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;应用示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ListView.separated(
	itemCount: 20,
	padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
	itemBuilder: (context, index) {
		return ListTile(
			title: Text(&apos;消息 $index&apos;),
			subtitle: const Text(&apos;这是一条消息预览&apos;),
		);
	},
	separatorBuilder: (context, index) {
		return const Divider(height: 1);
	},
)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;4. 三种滚动组件对比&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;组件&lt;/th&gt;
&lt;th&gt;渲染方式&lt;/th&gt;
&lt;th&gt;适合场景&lt;/th&gt;
&lt;th&gt;优点&lt;/th&gt;
&lt;th&gt;注意点&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;SingleChildScrollView&lt;/td&gt;
&lt;td&gt;一次性渲染全部内容&lt;/td&gt;
&lt;td&gt;内容不多、结构灵活页面&lt;/td&gt;
&lt;td&gt;使用简单&lt;/td&gt;
&lt;td&gt;内容太多会影响性能&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ListView.builder&lt;/td&gt;
&lt;td&gt;按需渲染&lt;/td&gt;
&lt;td&gt;长列表、大数据量&lt;/td&gt;
&lt;td&gt;性能好&lt;/td&gt;
&lt;td&gt;item 结构建议稳定&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ListView.separated&lt;/td&gt;
&lt;td&gt;按需渲染 + 分隔构建&lt;/td&gt;
&lt;td&gt;需要分割线的长列表&lt;/td&gt;
&lt;td&gt;结构清晰&lt;/td&gt;
&lt;td&gt;分隔线逻辑单独维护&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;5. 学习小结&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;页面内容总量少：优先 &lt;code&gt;SingleChildScrollView&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;大数据列表：优先 &lt;code&gt;ListView.builder&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;大数据且要分隔效果：优先 &lt;code&gt;ListView.separated&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;需要程序化滚动控制时，搭配 &lt;code&gt;ScrollController&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Flutter Day04: GridView 与 CustomScrollView</title><link>https://zgq1008.github.io/posts/flutter/flutter_day04/</link><guid isPermaLink="true">https://zgq1008.github.io/posts/flutter/flutter_day04/</guid><description>梳理 GridView 与 CustomScrollView 的布局模式、常用属性和示例。</description><pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Flutter Day04：GridView 与 CustomScrollView 知识点&lt;/h1&gt;
&lt;h2&gt;1. GridView 组件概述&lt;/h2&gt;
&lt;p&gt;GridView 用于展示二维网格列表，适合图片墙、商品列表等网格布局页面。&lt;/p&gt;
&lt;p&gt;核心特点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;支持滚动。&lt;/li&gt;
&lt;li&gt;支持网格布局（按列数或按最大宽度）。&lt;/li&gt;
&lt;li&gt;支持按需渲染（懒加载），只构建当前可见区域的 item，离开可视区域的 item 会被回收，性能更好。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;2. GridView.count 模式（按列数布局）&lt;/h2&gt;
&lt;h3&gt;常用属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;crossAxisCount：每行（垂直滚动时）的列数。&lt;/li&gt;
&lt;li&gt;mainAxisSpacing：主轴方向 item 间距。&lt;/li&gt;
&lt;li&gt;crossAxisSpacing：交叉轴方向 item 间距。&lt;/li&gt;
&lt;li&gt;childAspectRatio：item 宽高比（宽 / 高）。&lt;/li&gt;
&lt;li&gt;padding：GridView 内边距。&lt;/li&gt;
&lt;li&gt;scrollDirection：滚动方向，默认 Axis.vertical。&lt;/li&gt;
&lt;li&gt;children：直接传入子组件列表。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;示例代码&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class MyGridView1 extends StatefulWidget {
	const MyGridView1({super.key});

	@override
	State&amp;lt;MyGridView1&amp;gt; createState() =&amp;gt; _MyGridViewState1();
}

class _MyGridViewState1 extends State&amp;lt;MyGridView1&amp;gt; {
	final ScrollController _scrollController = ScrollController();

	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			home: Scaffold(
				appBar: AppBar(title: const Text(&quot;GridView.count&quot;)),
				body: GridView.count(
					controller: _scrollController,
					scrollDirection: Axis.vertical,
					crossAxisCount: 3,
					mainAxisSpacing: 10,
					crossAxisSpacing: 10,
					childAspectRatio: 1,
					padding: const EdgeInsets.all(20),
					children: List.generate(100, (index) {
						return Container(
							color: Colors.blue,
							alignment: Alignment.center,
							child: Text(
								&quot;Item $index&quot;,
								style: const TextStyle(color: Colors.white, fontSize: 20),
							),
						);
					}),
				),
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;3. GridView.extent 模式（按最大宽度布局）&lt;/h2&gt;
&lt;p&gt;GridView.extent 通过 maxCrossAxisExtent 控制 item 最大宽度，列数会根据屏幕宽度自动变化。&lt;/p&gt;
&lt;p&gt;例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;item 最大宽度为 100。&lt;/li&gt;
&lt;li&gt;屏幕足够宽时每行可放 3 个。&lt;/li&gt;
&lt;li&gt;屏幕变窄后会自动降为 2 个或 1 个。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;常用属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;maxCrossAxisExtent：每个 item 在交叉轴方向的最大尺寸。&lt;/li&gt;
&lt;li&gt;mainAxisSpacing：主轴方向 item 间距。&lt;/li&gt;
&lt;li&gt;crossAxisSpacing：交叉轴方向 item 间距。&lt;/li&gt;
&lt;li&gt;childAspectRatio：item 宽高比。&lt;/li&gt;
&lt;li&gt;padding：内边距。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;示例代码&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class MyGridView2 extends StatefulWidget {
	const MyGridView2({super.key});

	@override
	State&amp;lt;MyGridView2&amp;gt; createState() =&amp;gt; _MyGridViewState2();
}

class _MyGridViewState2 extends State&amp;lt;MyGridView2&amp;gt; {
	final ScrollController _scrollController = ScrollController();

	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			home: Scaffold(
				appBar: AppBar(title: const Text(&quot;GridView.extent&quot;)),
				body: GridView.extent(
					controller: _scrollController,
					scrollDirection: Axis.vertical,
					maxCrossAxisExtent: 100,
					mainAxisSpacing: 10,
					crossAxisSpacing: 10,
					childAspectRatio: 1,
					padding: const EdgeInsets.all(20),
					children: List.generate(100, (index) {
						return Container(
							color: Colors.blue,
							alignment: Alignment.center,
							child: Text(
								&quot;Item $index&quot;,
								style: const TextStyle(color: Colors.white, fontSize: 20),
							),
						);
					}),
				),
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;4. GridView.builder 模式（推荐大数据量）&lt;/h2&gt;
&lt;p&gt;GridView.builder 适合大量数据场景，按需构建 item。&lt;/p&gt;
&lt;h3&gt;常用属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;itemBuilder：构建每个 item 的回调，参数为 context 和 index。&lt;/li&gt;
&lt;li&gt;itemCount：item 总数量。&lt;/li&gt;
&lt;li&gt;gridDelegate：网格布局规则。&lt;/li&gt;
&lt;li&gt;padding：内边距。&lt;/li&gt;
&lt;li&gt;scrollDirection：滚动方向。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;gridDelegate 常见类型&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;SliverGridDelegateWithFixedCrossAxisCount：按固定列数布局。&lt;/li&gt;
&lt;li&gt;SliverGridDelegateWithMaxCrossAxisExtent：按最大宽度布局。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;示例代码&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class MyGridView3 extends StatefulWidget {
	const MyGridView3({super.key});

	@override
	State&amp;lt;MyGridView3&amp;gt; createState() =&amp;gt; _MyGridViewState3();
}

class _MyGridViewState3 extends State&amp;lt;MyGridView3&amp;gt; {
	final ScrollController _scrollController = ScrollController();

	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			home: Scaffold(
				appBar: AppBar(title: const Text(&quot;GridView.builder&quot;)),
				body: GridView.builder(
					controller: _scrollController,
					scrollDirection: Axis.vertical,
					padding: const EdgeInsets.all(20),
					gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
						crossAxisCount: 3,
						mainAxisSpacing: 10,
						crossAxisSpacing: 10,
						childAspectRatio: 1,
					),
					itemCount: 100,
					itemBuilder: (BuildContext context, int index) {
						return Container(
							color: Colors.blue,
							alignment: Alignment.center,
							child: Text(
								&quot;Item $index&quot;,
								style: const TextStyle(color: Colors.white, fontSize: 20),
							),
						);
					},
				),
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;5. CustomScrollView 组件概述&lt;/h2&gt;
&lt;p&gt;CustomScrollView 用于组合多个可滚动区域，并支持更灵活的滚动效果（如轮播图、吸顶分类、混合列表等）。&lt;/p&gt;
&lt;p&gt;关键点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;slivers 参数中只能放 Sliver 组件。&lt;/li&gt;
&lt;li&gt;不能直接放普通 Container（可用 SliverToBoxAdapter 包裹）。&lt;/li&gt;
&lt;li&gt;常见 Sliver：
&lt;ul&gt;
&lt;li&gt;SliverToBoxAdapter：包裹普通组件。&lt;/li&gt;
&lt;li&gt;SliverList：列表。&lt;/li&gt;
&lt;li&gt;SliverGrid：网格。&lt;/li&gt;
&lt;li&gt;SliverPersistentHeader：可配置吸顶头部。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;轮播图相关状态与属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;_currentPage：当前轮播页索引，用于更新分页小圆点颜色。&lt;/li&gt;
&lt;li&gt;PageController：控制 PageView 翻页。&lt;/li&gt;
&lt;li&gt;onPageChanged：监听手势滑动后的页码变化。&lt;/li&gt;
&lt;li&gt;animateToPage：点击小圆点时平滑跳转到指定页。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;SliverPersistentHeader 相关属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;pinned: true：吸顶固定。&lt;/li&gt;
&lt;li&gt;floating: false：不会在反向滚动时立即浮现。&lt;/li&gt;
&lt;li&gt;delegate：头部布局和行为委托。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;示例代码&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class MyCustomScrollView extends StatefulWidget {
	const MyCustomScrollView({super.key});

	@override
	State&amp;lt;MyCustomScrollView&amp;gt; createState() =&amp;gt; _MyCustomScrollViewState();
}

class _MyCustomScrollViewState extends State&amp;lt;MyCustomScrollView&amp;gt; {
	int _currentPage = 0;
	final PageController _pageController = PageController();

	@override
	Widget build(BuildContext context) {
		return MaterialApp(
			home: Scaffold(
				appBar: AppBar(title: const Text(&quot;CustomScrollView&quot;)),
				body: CustomScrollView(
					slivers: [
						SliverToBoxAdapter(
							child: Stack(
								children: [
									Container(
										height: 260,
										color: Colors.blue,
										alignment: Alignment.center,
										child: PageView.builder(
											controller: _pageController,
											onPageChanged: (index) {
												setState(() {
													_currentPage = index;
												});
											},
											itemBuilder: (BuildContext context, int index) {
												return Container(
													color: Colors.blue,
													alignment: Alignment.center,
													child: Text(
														&quot;轮播图 $index&quot;,
														style: const TextStyle(color: Colors.white, fontSize: 20),
													),
												);
											},
											itemCount: 10,
										),
									),
									Positioned(
										bottom: 0,
										left: 0,
										right: 0,
										height: 30,
										child: Row(
											mainAxisAlignment: MainAxisAlignment.center,
											children: List.generate(10, (index) {
												return GestureDetector(
													onTap: () {
														_pageController.animateToPage(
															index,
															duration: const Duration(milliseconds: 300),
															curve: Curves.easeInOut,
														);
														setState(() {
															_currentPage = index;
														});
													},
													child: Container(
														width: 10,
														height: 10,
														margin: const EdgeInsets.symmetric(horizontal: 10),
														decoration: BoxDecoration(
															color: _currentPage == index ? Colors.red : Colors.grey,
															shape: BoxShape.circle,
														),
													),
												);
											}),
										),
									),
								],
							),
						),
						const SliverToBoxAdapter(
							child: SizedBox(height: 20),
						),
						SliverPersistentHeader(
							delegate: _StickyCategory(),
							floating: false,
							pinned: true,
						),
						SliverList.separated(
							itemCount: 100,
							itemBuilder: (BuildContext context, int index) {
								return Container(
									alignment: Alignment.center,
									width: double.infinity,
									height: 100,
									color: Colors.blue,
									child: Text(
										&quot;Item $index&quot;,
										style: const TextStyle(color: Colors.white, fontSize: 20),
									),
								);
							},
							separatorBuilder: (BuildContext context, int index) {
								return const SizedBox(height: 10);
							},
						),
					],
				),
			),
		);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;6. SliverPersistentHeaderDelegate 吸顶头部&lt;/h2&gt;
&lt;p&gt;通过自定义 SliverPersistentHeaderDelegate，可以实现吸顶分类栏。&lt;/p&gt;
&lt;h3&gt;关键方法与属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;build(context, shrinkOffset, overlapsContent)：构建头部 UI。
&lt;ul&gt;
&lt;li&gt;shrinkOffset：头部收缩量。&lt;/li&gt;
&lt;li&gt;overlapsContent：是否与下方内容重叠。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;maxExtent：头部最大高度。&lt;/li&gt;
&lt;li&gt;minExtent：头部最小高度。&lt;/li&gt;
&lt;li&gt;shouldRebuild(oldDelegate)：是否需要重建。
&lt;ul&gt;
&lt;li&gt;头部配置不变时返回 false，可提升性能。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;示例代码&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;class _StickyCategory extends SliverPersistentHeaderDelegate {
	@override
	Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
		return Container(
			color: Colors.white,
			child: ListView.builder(
				scrollDirection: Axis.horizontal,
				itemCount: 10,
				itemBuilder: (BuildContext context, int index) {
					return Container(
						alignment: Alignment.center,
						width: 100,
						height: 60,
						margin: const EdgeInsets.symmetric(horizontal: 10),
						color: Colors.blue,
						child: Text(
							&quot;分类 $index&quot;,
							style: const TextStyle(color: Colors.white, fontSize: 20),
						),
					);
				},
			),
		);
	}

	@override
	double get maxExtent =&amp;gt; 80;

	@override
	double get minExtent =&amp;gt; 60;

	@override
	bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
		return false;
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;7. PageView 轮播补充知识点&lt;/h2&gt;
&lt;p&gt;在你的代码里，轮播图通过 PageView.builder 放在 SliverToBoxAdapter 中，再用 Stack + Positioned 叠加分页指示器。&lt;/p&gt;
&lt;p&gt;这种实现的优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;轮播区域属于整页滚动的一部分，可与下方 Sliver 一起滚动。&lt;/li&gt;
&lt;li&gt;指示器覆盖在轮播图底部，UI 更接近电商首页效果。&lt;/li&gt;
&lt;li&gt;手势滑动与点击圆点都能更新 _currentPage，交互一致。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;建议补充：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;在 State 中重写 dispose，释放 _pageController，避免内存泄漏。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;@override
void dispose() {
	_pageController.dispose();
	super.dispose();
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;8. 选型建议&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;数据量小、结构固定：优先 GridView.count。&lt;/li&gt;
&lt;li&gt;需要自适应列数：使用 GridView.extent。&lt;/li&gt;
&lt;li&gt;数据量大或来自接口分页：使用 GridView.builder。&lt;/li&gt;
&lt;li&gt;页面有复杂滚动交互（吸顶、折叠、混合布局）：使用 CustomScrollView + Sliver。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>Flutter Day01: 布局与状态管理核心</title><link>https://zgq1008.github.io/posts/flutter/flutter_day01/</link><guid isPermaLink="true">https://zgq1008.github.io/posts/flutter/flutter_day01/</guid><description>Flutter 布局规则、StatefulWidget 与常见基础组件学习笔记。</description><pubDate>Mon, 06 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Flutter 核心知识点笔记&lt;/h1&gt;
&lt;blockquote&gt;
&lt;p&gt;适用对象：Flutter 初学者到进阶开发者&lt;br /&gt;
学习目标：掌握常见布局组件、状态更新机制，并能根据场景选择合适组件&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;快速导航&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%B8%83%E5%B1%80%E6%A0%B8%E5%BF%83%E8%A7%84%E5%88%99&quot;&gt;布局核心规则&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%B8%80statefulwidget-%E4%B8%8E-setstate-%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86&quot;&gt;一、StatefulWidget 与 setState 状态管理&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BA%8Ccontainer-%E5%AE%B9%E5%99%A8%E7%BB%84%E4%BB%B6%E8%AF%A6%E8%A7%A3&quot;&gt;二、Container 容器组件详解&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%B8%89scaffold-%E9%A1%B5%E9%9D%A2%E9%AA%A8%E6%9E%B6%E7%BB%84%E4%BB%B6&quot;&gt;三、Scaffold 页面骨架组件&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%9B%9Balign-%E4%B8%8E-container-%E7%9A%84%E5%B5%8C%E5%A5%97%E5%85%B3%E7%B3%BB&quot;&gt;四、Align 与 Container 的嵌套关系&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BA%94padding%E5%86%85%E8%BE%B9%E8%B7%9D%E7%BB%84%E4%BB%B6&quot;&gt;五、Padding（内边距组件）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%85%AD%E7%BA%BF%E6%80%A7%E5%B8%83%E5%B1%80row-%E4%B8%8E-column&quot;&gt;六、线性布局：Row 与 Column&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%B8%83flex%E5%BC%B9%E6%80%A7%E5%B8%83%E5%B1%80&quot;&gt;七、Flex（弹性布局）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%85%ABwrap%E6%B5%81%E5%BC%8F%E5%B8%83%E5%B1%80&quot;&gt;八、Wrap（流式布局）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%B9%9D%E5%B8%B8%E8%A7%81%E6%98%93%E9%94%99%E7%82%B9%E9%80%9F%E6%9F%A5&quot;&gt;九、常见易错点速查&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%8D%81%E7%BB%BC%E5%90%88%E6%A1%88%E4%BE%8B%E6%9E%84%E5%BB%BA%E4%B8%80%E4%B8%AA%E5%8F%AF%E8%87%AA%E9%80%82%E5%BA%94%E7%9A%84%E5%8D%A1%E7%89%87%E5%8C%BA%E5%9F%9F&quot;&gt;十、综合案例：构建一个可自适应的卡片区域&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%8D%81%E4%B8%80stack%E5%B1%82%E5%8F%A0%E5%B8%83%E5%B1%80%E7%BB%84%E4%BB%B6&quot;&gt;十一、Stack（层叠布局组件）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%8D%81%E4%BA%8Ctext%E6%96%87%E6%9C%AC%E7%BB%84%E4%BB%B6&quot;&gt;十二、Text（文本组件）&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%8D%81%E4%B8%89textspan-%E4%B8%8E-richtext%E5%AF%8C%E6%96%87%E6%9C%AC&quot;&gt;十三、TextSpan 与 RichText（富文本）&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;布局遵循规则&lt;/h2&gt;
&lt;p&gt;在 Flutter 中，布局遵循“向下传递约束，向上传递尺寸”的原则。&lt;/p&gt;
&lt;h2&gt;布局核心规则&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;父组件向子组件传递约束（Constraints）。&lt;/li&gt;
&lt;li&gt;子组件在约束内确定自身尺寸（Size）。&lt;/li&gt;
&lt;li&gt;子组件将尺寸回传给父组件，父组件再决定其位置（Position）。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;理解这个规则后，很多“为什么不生效”或“为什么溢出”的问题会更容易定位。&lt;/p&gt;
&lt;h2&gt;一、StatefulWidget 与 setState 状态管理&lt;/h2&gt;
&lt;p&gt;在 Flutter 中，当页面上的数据发生变化且需要实时更新 UI 时，通常要使用 &lt;code&gt;StatefulWidget&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;1. 核心机制&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;StatefulWidget&lt;/code&gt;：组件本身是不可变的，它通过 &lt;code&gt;createState()&lt;/code&gt; 创建一个 &lt;code&gt;State&lt;/code&gt; 对象。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;State&lt;/code&gt; 对象：存储组件的可变数据（如代码中的 &lt;code&gt;count&lt;/code&gt;），并负责构建 UI。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;setState()&lt;/code&gt;：通知框架“状态已更改”的关键方法。调用后，Flutter 会将该组件标记为“脏”（dirty），并在下一帧触发 &lt;code&gt;build&lt;/code&gt; 方法重新运行，从而根据新数据渲染界面。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 代码中的具体应用&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;数据定义：&lt;code&gt;int count = 0;&lt;/code&gt;（定义在 &lt;code&gt;State&lt;/code&gt; 类中）。&lt;/li&gt;
&lt;li&gt;状态触发示例：&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;onPressed: () {
  count++; // 1. 修改变量值
  setState(() {}); // 2. 触发 UI 刷新
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;注意：&lt;code&gt;setState&lt;/code&gt; 内部通常包裹修改逻辑（如 &lt;code&gt;setState(() =&amp;gt; count++)&lt;/code&gt;）。但即使是空回调，只要调用了它，当前 Widget 及其子树就会重新构建。&lt;/p&gt;
&lt;h2&gt;二、Container 容器组件详解&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Container&lt;/code&gt; 是 Flutter 中常用的通用布局组件，它结合了绘制、定位和调整大小等功能。&lt;/p&gt;
&lt;h3&gt;1. 基础布局属性&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;描述&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;width&lt;/code&gt; / &lt;code&gt;height&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;设置容器的固定宽高（逻辑像素）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;width: 200&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alignment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制子组件（&lt;code&gt;child&lt;/code&gt;）在容器内的对齐方式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Alignment.center&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;margin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;容器外部与其他组件的间距（外边距）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;EdgeInsets.all(20.0)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;padding&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;容器内部边缘与子组件的间距（内边距）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;EdgeInsets.symmetric(...)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;对容器进行矩阵变换，如旋转、缩放、平移&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Matrix4.rotationZ(0.1)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2. BoxDecoration 装饰器&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;decoration&lt;/code&gt; 属性允许我们美化容器。&lt;/p&gt;
&lt;p&gt;注意：一旦使用了 &lt;code&gt;decoration&lt;/code&gt;，&lt;code&gt;Container&lt;/code&gt; 自身的 &lt;code&gt;color&lt;/code&gt; 属性必须移除。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;color&lt;/code&gt;：背景颜色（如 &lt;code&gt;Colors.blue&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;borderRadius&lt;/code&gt;：设置圆角（&lt;code&gt;BorderRadius.circular(15.0)&lt;/code&gt;）。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;border&lt;/code&gt;：设置边框颜色和宽度（&lt;code&gt;Border.all(color: Colors.amber, width: 3.0)&lt;/code&gt;）。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;三、Scaffold 页面骨架组件&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Scaffold&lt;/code&gt; 是 Material 风格页面的基础骨架组件，通常作为一个页面最外层的结构容器。&lt;/p&gt;
&lt;p&gt;它可以快速组织页面常见区域，例如：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;顶部导航栏（&lt;code&gt;appBar&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;页面主体内容区（&lt;code&gt;body&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;悬浮操作按钮（&lt;code&gt;floatingActionButton&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;抽屉菜单（&lt;code&gt;drawer&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;底部导航栏（&lt;code&gt;bottomNavigationBar&lt;/code&gt;）&lt;/li&gt;
&lt;li&gt;底部操作栏（&lt;code&gt;bottomSheet&lt;/code&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;1. 常用属性&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;th&gt;常见写法&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;appBar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;配置顶部应用栏&lt;/td&gt;
&lt;td&gt;&lt;code&gt;AppBar(title: Text(&apos;首页&apos;))&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;body&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;页面主体内容&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Center(child: Text(&apos;Hello&apos;))&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;floatingActionButton&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;悬浮按钮，常用于主要操作&lt;/td&gt;
&lt;td&gt;&lt;code&gt;FloatingActionButton(...)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;drawer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;左侧抽屉菜单&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Drawer(child: ListView(...))&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bottomNavigationBar&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;底部导航栏&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BottomNavigationBar(...)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;backgroundColor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;页面背景色&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Colors.grey[100]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2. 基础示例&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Scaffold(
  appBar: AppBar(
    title: const Text(&apos;Scaffold 示例&apos;),
  ),
  body: const Center(
    child: Text(&apos;页面内容区域&apos;),
  ),
  floatingActionButton: FloatingActionButton(
    onPressed: () {
      // 点击后执行主要操作
    },
    child: const Icon(Icons.add),
  ),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 使用建议&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;一个页面通常对应一个 &lt;code&gt;Scaffold&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;如果页面已经有外层 &lt;code&gt;Scaffold&lt;/code&gt;，子组件中一般不再重复嵌套，避免布局和返回行为混乱。&lt;/li&gt;
&lt;li&gt;需要显示提示条时，可结合 &lt;code&gt;ScaffoldMessenger&lt;/code&gt; 使用 &lt;code&gt;SnackBar&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;四、Align 与 Container 的嵌套关系&lt;/h2&gt;
&lt;h3&gt;1. &lt;code&gt;Align&lt;/code&gt; 放在 &lt;code&gt;Container&lt;/code&gt; 内部&lt;/h3&gt;
&lt;p&gt;结构：&lt;code&gt;Container -&amp;gt; Align -&amp;gt; Child&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;谁决定位置：&lt;code&gt;Align&lt;/code&gt; 决定子组件（&lt;code&gt;Child&lt;/code&gt;）在 &lt;code&gt;Container&lt;/code&gt; 内部的位置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Container&lt;/code&gt; 的表现：大小由自身 &lt;code&gt;width&lt;/code&gt;、&lt;code&gt;height&lt;/code&gt; 或父组件约束决定。&lt;/li&gt;
&lt;li&gt;实际效果：&lt;code&gt;Container&lt;/code&gt; 像一个固定画框，&lt;code&gt;Align&lt;/code&gt; 只是在画框内部移动内容。&lt;/li&gt;
&lt;li&gt;注意：不会改变 &lt;code&gt;Container&lt;/code&gt; 自身在屏幕中的位置。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Container(
  width: 200,
  height: 200,
  color: Colors.blue,
  child: Align(
    alignment: Alignment.bottomRight,
    child: Text(&quot;我在内部&quot;),
  ),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. &lt;code&gt;Container&lt;/code&gt; 放在 &lt;code&gt;Align&lt;/code&gt; 内部&lt;/h3&gt;
&lt;p&gt;结构：&lt;code&gt;Align -&amp;gt; Container -&amp;gt; Child&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;谁决定位置：&lt;code&gt;Align&lt;/code&gt; 决定整个 &lt;code&gt;Container&lt;/code&gt; 在父级空间中的位置。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Align&lt;/code&gt; 的表现：通常占据父组件可用空间，再按 &lt;code&gt;alignment&lt;/code&gt; 摆放子组件。&lt;/li&gt;
&lt;li&gt;实际效果：&lt;code&gt;Align&lt;/code&gt; 充当“定位员”，可解决 &lt;code&gt;Container&lt;/code&gt; 默认靠左上角的问题。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Align(
  alignment: Alignment.center,
  child: Container(
    width: 200,
    height: 200,
    color: Colors.blue,
    child: Text(&quot;我在中间&quot;),
  ),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;3. 核心区别对比&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;维度&lt;/th&gt;
&lt;th&gt;Container 套 Align&lt;/th&gt;
&lt;th&gt;Align 套 Container&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;控制对象&lt;/td&gt;
&lt;td&gt;控制子组件的对齐方式&lt;/td&gt;
&lt;td&gt;控制 Container 自身的对齐方式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;容器大小&lt;/td&gt;
&lt;td&gt;容器大小固定，子组件在里面动&lt;/td&gt;
&lt;td&gt;容器大小固定，容器在父空间里动&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;父级占用&lt;/td&gt;
&lt;td&gt;Container 仅占用设定的 &lt;code&gt;200x200&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Align 默认可填满父级可用空间&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;常见用途&lt;/td&gt;
&lt;td&gt;制作带复杂内部布局的卡片&lt;/td&gt;
&lt;td&gt;调整组件在页面中的摆放位置&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;4. 特殊情况：&lt;code&gt;Container&lt;/code&gt; 的 &lt;code&gt;alignment&lt;/code&gt; 属性&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;Container&lt;/code&gt; 内部已经集成了类似 &lt;code&gt;Align&lt;/code&gt; 的逻辑。示例：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Container(
  alignment: Alignment.center,
  child: Text(&quot;Hello&quot;),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这在逻辑上等同于“将 &lt;code&gt;Align&lt;/code&gt; 放在 &lt;code&gt;Container&lt;/code&gt; 内部”。
它只会让文字在容器中居中，不会让容器在页面中居中。&lt;/p&gt;
&lt;h3&gt;5. 总结建议&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;想让“盒子里的内容”换位置：把 &lt;code&gt;Align&lt;/code&gt; 放在 &lt;code&gt;Container&lt;/code&gt; 里，或直接使用 &lt;code&gt;Container.alignment&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;想让“整个盒子”换位置：把 &lt;code&gt;Container&lt;/code&gt; 放在 &lt;code&gt;Align&lt;/code&gt; 里。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;五、Padding（内边距组件）&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Padding&lt;/code&gt; 专门用于给子组件增加内边距。&lt;/p&gt;
&lt;h3&gt;1. 核心属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;padding&lt;/code&gt;：接收 &lt;code&gt;EdgeInsetsGeometry&lt;/code&gt; 类型。&lt;/li&gt;
&lt;li&gt;常见写法：
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;EdgeInsets.all(10.0)&lt;/code&gt;：四周相等。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EdgeInsets.symmetric(horizontal: 20.0, vertical: 10.0)&lt;/code&gt;：水平和垂直对称。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EdgeInsets.only(left: 10, top: 5)&lt;/code&gt;：指定单边。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;EdgeInsets.fromLTRB(left, top, right, bottom)&lt;/code&gt;：按左上右下设置。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 知识点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Padding&lt;/code&gt; 是单一职责组件，只负责间距，通常比通用 &lt;code&gt;Container&lt;/code&gt; 更轻量。&lt;/li&gt;
&lt;li&gt;需要多层间距时，可嵌套多个 &lt;code&gt;Padding&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 案例代码与实际效果&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Container(
  color: Colors.grey.shade300,
  child: Padding(
    padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),//横向和纵向
    child: Container(
      color: Colors.blue,
      child: const Text(
        &apos;有内边距的文本&apos;,
        style: TextStyle(color: Colors.white),
      ),
    ),
  ),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际效果：蓝色内容块不会贴着灰色边缘，而是与四周保持稳定留白，视觉更舒展。&lt;/p&gt;
&lt;h2&gt;六、线性布局：Row 与 Column&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Row&lt;/code&gt; 和 &lt;code&gt;Column&lt;/code&gt; 分别用于水平方向与垂直方向排列子组件。&lt;/p&gt;
&lt;h3&gt;1. 核心属性&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;功能&lt;/th&gt;
&lt;th&gt;备注&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;children&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;接收 &lt;code&gt;List&amp;lt;Widget&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;放置多个子组件&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mainAxisAlignment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;主轴对齐方式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Row&lt;/code&gt; 主轴水平，&lt;code&gt;Column&lt;/code&gt; 主轴垂直&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;crossAxisAlignment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;交叉轴对齐方式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Row&lt;/code&gt; 交叉轴垂直，&lt;code&gt;Column&lt;/code&gt; 交叉轴水平&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mainAxisSize&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;主轴占用大小&lt;/td&gt;
&lt;td&gt;&lt;code&gt;MainAxisSize.max&lt;/code&gt; 或 &lt;code&gt;MainAxisSize.min&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2. 常见主轴对齐值&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;MainAxisAlignment.start&lt;/code&gt;：起点对齐。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MainAxisAlignment.center&lt;/code&gt;：居中。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MainAxisAlignment.end&lt;/code&gt;：终点对齐。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MainAxisAlignment.spaceBetween&lt;/code&gt;：两端贴边，中间均匀分隔。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MainAxisAlignment.spaceAround&lt;/code&gt;：每个子项两侧间距相等。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;MainAxisAlignment.spaceEvenly&lt;/code&gt;：所有间距（含两端）完全相等。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 案例代码与实际效果&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Row(
  mainAxisAlignment: MainAxisAlignment.spaceEvenly,
  children: const [
    Icon(Icons.home, size: 32),
    Icon(Icons.search, size: 32),
    Icon(Icons.person, size: 32),
  ],
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际效果：三个图标在一行中平均分布，左右留白与图标间距保持一致。&lt;/p&gt;
&lt;h2&gt;七、Flex（弹性布局）&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Flex&lt;/code&gt; 是 &lt;code&gt;Row&lt;/code&gt; 与 &lt;code&gt;Column&lt;/code&gt; 的底层通用形式。&lt;/p&gt;
&lt;h3&gt;1. 核心属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;direction&lt;/code&gt;：必填。
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Axis.horizontal&lt;/code&gt; 等同于 &lt;code&gt;Row&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Axis.vertical&lt;/code&gt; 等同于 &lt;code&gt;Column&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 配合组件：&lt;code&gt;Expanded&lt;/code&gt; 与 &lt;code&gt;Flexible&lt;/code&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Expanded&lt;/code&gt;：强制子项填满主轴剩余空间。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Flexible&lt;/code&gt;：允许子项参与弹性分配，但不强制填满。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flex&lt;/code&gt;：分配权重，默认是 &lt;code&gt;1&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 案例代码与实际效果&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Flex(
  direction: Axis.horizontal,
  children: [
    Expanded(
      flex: 2,
      child: Container(height: 60, color: Colors.red),
    ),
    Expanded(
      flex: 1,
      child: Container(height: 60, color: Colors.green),
    ),
  ],
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际效果：红色与绿色区域按 &lt;code&gt;2:1&lt;/code&gt; 分配宽度，红色区域约为绿色的两倍。&lt;/p&gt;
&lt;h2&gt;八、Wrap（流式布局）&lt;/h2&gt;
&lt;p&gt;当 &lt;code&gt;Row&lt;/code&gt; 或 &lt;code&gt;Column&lt;/code&gt; 子组件超出可用空间时，容易出现 &lt;code&gt;Overflow&lt;/code&gt;。&lt;code&gt;Wrap&lt;/code&gt; 可自动换行（或换列）。&lt;/p&gt;
&lt;h3&gt;1. 核心属性&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;direction&lt;/code&gt;：排列方向，默认 &lt;code&gt;Axis.horizontal&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;spacing&lt;/code&gt;：主轴方向子项间距。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runSpacing&lt;/code&gt;：换行后行与行之间间距。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;alignment&lt;/code&gt;：每一行在主轴上的对齐方式。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;runAlignment&lt;/code&gt;：多行整体在交叉轴上的对齐方式。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 知识点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;组件数量不确定时（如标签云、筛选项），优先考虑 &lt;code&gt;Wrap&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;相比 &lt;code&gt;Row&lt;/code&gt;，&lt;code&gt;Wrap&lt;/code&gt; 能在小屏设备上更自然适配。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 案例代码与实际效果&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Wrap(
  spacing: 8,
  runSpacing: 8,
  children: [
    for (final tag in [&apos;Flutter&apos;, &apos;Dart&apos;, &apos;状态管理&apos;, &apos;布局&apos;, &apos;动画&apos;, &apos;网络&apos;])
      Chip(label: Text(tag)),
  ],
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际效果：标签在一行放不下时会自动换到下一行，避免右侧溢出报错。&lt;/p&gt;
&lt;h2&gt;九、常见易错点速查&lt;/h2&gt;
&lt;h3&gt;1. &lt;code&gt;setState&lt;/code&gt; 调用了但界面没更新&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;常见原因：修改的变量不在当前 &lt;code&gt;State&lt;/code&gt; 中，或 UI 没有使用该变量。&lt;/li&gt;
&lt;li&gt;解决建议：确认“数据定义位置”和“build 中是否读取该数据”。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. &lt;code&gt;Container&lt;/code&gt; 设置了 &lt;code&gt;decoration&lt;/code&gt; 又设置 &lt;code&gt;color&lt;/code&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;常见原因：同一层同时设置 &lt;code&gt;decoration&lt;/code&gt; 和 &lt;code&gt;color&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;解决建议：颜色放到 &lt;code&gt;BoxDecoration(color: ...)&lt;/code&gt; 中，不再单独写 &lt;code&gt;color&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. &lt;code&gt;Row&lt;/code&gt; 子项过多出现黄色黑纹溢出&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;常见原因：&lt;code&gt;Row&lt;/code&gt; 不会自动换行。&lt;/li&gt;
&lt;li&gt;解决建议：改用 &lt;code&gt;Wrap&lt;/code&gt;，或配合 &lt;code&gt;Expanded/Flexible&lt;/code&gt; 做弹性压缩。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 以为 &lt;code&gt;Container(alignment: ...)&lt;/code&gt; 能移动整个容器&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;常见原因：混淆“内容对齐”和“组件定位”。&lt;/li&gt;
&lt;li&gt;解决建议：&lt;code&gt;Container.alignment&lt;/code&gt; 只影响子组件；要移动整个容器，使用外层 &lt;code&gt;Align&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;十、综合案例：构建一个可自适应的卡片区域&lt;/h2&gt;
&lt;p&gt;下面的示例同时使用了 &lt;code&gt;Scaffold&lt;/code&gt;、&lt;code&gt;setState&lt;/code&gt;、&lt;code&gt;Padding&lt;/code&gt;、&lt;code&gt;Wrap&lt;/code&gt;、&lt;code&gt;Container&lt;/code&gt; 和 &lt;code&gt;Align&lt;/code&gt;。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;class DemoPage extends StatefulWidget {
  const DemoPage({super.key});

  @override
  State&amp;lt;DemoPage&amp;gt; createState() =&amp;gt; _DemoPageState();
}

class _DemoPageState extends State&amp;lt;DemoPage&amp;gt; {
  int count = 0;
  final List&amp;lt;String&amp;gt; tags = [&apos;Flutter&apos;, &apos;布局&apos;, &apos;状态&apos;, &apos;组件化&apos;, &apos;响应式&apos;];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text(&apos;综合案例&apos;)),
      floatingActionButton: FloatingActionButton(
        onPressed: () =&amp;gt; setState(() =&amp;gt; count++),
        child: const Icon(Icons.add),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              width: double.infinity,
              padding: const EdgeInsets.all(16),
              decoration: BoxDecoration(
                color: Colors.blue.shade50,
                borderRadius: BorderRadius.circular(12),
                border: Border.all(color: Colors.blue.shade200),
              ),
              child: Align(
                alignment: Alignment.centerLeft,
                child: Text(&apos;点击次数：$count&apos;, style: const TextStyle(fontSize: 18)),
              ),
            ),
            const SizedBox(height: 16),
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                for (final tag in tags) Chip(label: Text(tag)),
              ],
            ),
          ],
        ),
      ),
    );
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际效果：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;点击右下角按钮，顶部计数文本实时刷新。&lt;/li&gt;
&lt;li&gt;卡片区域有统一内边距、圆角和边框，视觉层次清晰。&lt;/li&gt;
&lt;li&gt;标签区会随屏幕宽度自动换行，小屏设备也不易溢出。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;十一、Stack（层叠布局组件）&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Stack&lt;/code&gt; 允许子组件按绘制顺序叠放。通常后添加的子组件会显示在更上层。&lt;/p&gt;
&lt;h3&gt;1. 核心属性&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;功能&lt;/th&gt;
&lt;th&gt;常见值&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alignment&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制未定位子组件的对齐方式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Alignment.center&lt;/code&gt;、&lt;code&gt;Alignment.bottomRight&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;控制非定位子组件如何适应 &lt;code&gt;Stack&lt;/code&gt; 大小&lt;/td&gt;
&lt;td&gt;&lt;code&gt;StackFit.loose&lt;/code&gt;（默认）、&lt;code&gt;StackFit.expand&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clipBehavior&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;子组件超出范围时的裁剪策略&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Clip.none&lt;/code&gt;、&lt;code&gt;Clip.hardEdge&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;children&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;子组件列表，后面的会覆盖前面的&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2. 配合组件：&lt;code&gt;Positioned&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;Stack&lt;/code&gt; 中，通常使用 &lt;code&gt;Positioned&lt;/code&gt; 精确控制子组件位置。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;常用属性：&lt;code&gt;top&lt;/code&gt;、&lt;code&gt;bottom&lt;/code&gt;、&lt;code&gt;left&lt;/code&gt;、&lt;code&gt;right&lt;/code&gt;、&lt;code&gt;width&lt;/code&gt;、&lt;code&gt;height&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;关键点：一旦子组件被 &lt;code&gt;Positioned&lt;/code&gt; 包裹，它会变成“定位组件”，不再受 &lt;code&gt;Stack.alignment&lt;/code&gt; 影响。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 案例代码与实际效果&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Stack(
  children: [
    Container(
      width: 220,
      height: 120,
      decoration: BoxDecoration(
        color: Colors.blue.shade100,
        borderRadius: BorderRadius.circular(12),
      ),
    ),
    Positioned(
      top: 8,
      right: 8,
      child: Container(
        padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4),
        decoration: BoxDecoration(
          color: Colors.red,
          borderRadius: BorderRadius.circular(10),
        ),
        child: const Text(&apos;NEW&apos;, style: TextStyle(color: Colors.white)),
      ),
    ),
  ],
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际效果：蓝色卡片右上角叠加一个红色角标，常用于消息数量、活动状态等提示场景。&lt;/p&gt;
&lt;h2&gt;十二、Text（文本组件）&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Text&lt;/code&gt; 用于显示单一样式或轻量样式的字符串内容。&lt;/p&gt;
&lt;h3&gt;1. 核心属性&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;作用&lt;/th&gt;
&lt;th&gt;示例&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;data&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文本内容（位置参数）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Text(&apos;Flutter&apos;)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;文本样式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TextStyle(fontSize: 16)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;textAlign&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;水平对齐方式&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TextAlign.center&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;overflow&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;溢出处理&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TextOverflow.ellipsis&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;maxLines&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;最大显示行数&lt;/td&gt;
&lt;td&gt;&lt;code&gt;maxLines: 2&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;textScaler&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;字体缩放策略（新写法）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TextScaler.linear(1.1)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;2. &lt;code&gt;TextStyle&lt;/code&gt; 常用配置&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;color&lt;/code&gt;：文本颜色。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fontSize&lt;/code&gt;：字号。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fontWeight&lt;/code&gt;：字重，如 &lt;code&gt;FontWeight.bold&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;fontStyle&lt;/code&gt;：斜体，如 &lt;code&gt;FontStyle.italic&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;letterSpacing&lt;/code&gt;：字间距。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;height&lt;/code&gt;：行高倍数，例如 &lt;code&gt;height: 1.5&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 案例代码与实际效果&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;const Text(
  &apos;这是一段很长的说明文字，超出两行后会显示省略号，避免破坏列表布局。&apos;,
  maxLines: 2,
  overflow: TextOverflow.ellipsis,
  style: TextStyle(fontSize: 14, height: 1.4),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;实际效果：文本最多显示两行，第三行内容被省略，适合卡片列表和新闻摘要场景。&lt;/p&gt;
&lt;h2&gt;十三、TextSpan 与 RichText（富文本）&lt;/h2&gt;
&lt;p&gt;当一句话里需要多种颜色、字号、字重，或希望某一段文字可点击时，应使用 &lt;code&gt;Text.rich&lt;/code&gt; / &lt;code&gt;RichText&lt;/code&gt; + &lt;code&gt;TextSpan&lt;/code&gt;。&lt;/p&gt;
&lt;h3&gt;1. 核心结构&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;TextSpan&lt;/code&gt; 不是组件（&lt;code&gt;Widget&lt;/code&gt;），而是文本片段描述对象。&lt;/li&gt;
&lt;li&gt;通过 &lt;code&gt;children&lt;/code&gt; 形成树形结构，子片段会继承父级样式。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;Text.rich(
  TextSpan(
    text: &apos;同意并继续：&apos;,
    style: const TextStyle(color: Colors.black87),
    children: [
      TextSpan(
        text: &apos;《用户协议》&apos;,
        style: const TextStyle(
          color: Colors.blue,
          fontWeight: FontWeight.bold,
          decoration: TextDecoration.underline,
        ),
      ),
      const TextSpan(text: &apos; 与 &apos;),
      TextSpan(
        text: &apos;《隐私政策》&apos;,
        style: const TextStyle(
          color: Colors.blue,
          fontWeight: FontWeight.bold,
          decoration: TextDecoration.underline,
        ),
      ),
    ],
  ),
)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;2. 常用属性速查&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;属性&lt;/th&gt;
&lt;th&gt;说明&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;当前片段文本&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;当前片段样式&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;children&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;子片段列表（&lt;code&gt;List&amp;lt;InlineSpan&amp;gt;&lt;/code&gt;）&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;recognizer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;手势识别器，用于点击事件&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;3. 点击事件注意点&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;使用 &lt;code&gt;TapGestureRecognizer&lt;/code&gt; 时，若在 &lt;code&gt;StatefulWidget&lt;/code&gt; 中长期持有，需要在 &lt;code&gt;dispose&lt;/code&gt; 中释放，避免内存泄漏。&lt;/li&gt;
&lt;li&gt;对可点击文本建议增加视觉提示（颜色、下划线），提高可用性。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;4. 适用场景建议&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;协议勾选说明（如“同意《用户协议》”）。&lt;/li&gt;
&lt;li&gt;价格文本（如“原价 + 现价”不同样式）。&lt;/li&gt;
&lt;li&gt;关键词高亮（搜索结果关键字着色）。&lt;/li&gt;
&lt;/ul&gt;
</content:encoded></item><item><title>MarkDown基础教程</title><link>https://zgq1008.github.io/posts/markdown_foundation/</link><guid isPermaLink="true">https://zgq1008.github.io/posts/markdown_foundation/</guid><description>从零开始掌握 Markdown，包含语法、排版规范与实战技巧</description><pubDate>Sat, 21 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Markdown 入门与进阶实战教程&lt;/h1&gt;
&lt;p&gt;这篇文章按“能马上写出一篇规范博客”为目标，带你从基础语法到实战排版一步走完。看完后，你应该可以：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;独立写出结构清晰的 Markdown 文档。&lt;/li&gt;
&lt;li&gt;用 VS Code 高效预览、管理和导出内容。&lt;/li&gt;
&lt;li&gt;避开常见语法坑，让文章在不同平台都稳定显示。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;目录&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%87%86%E5%A4%87%E5%B7%A5%E4%BD%9C&quot;&gt;一、准备工作&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95&quot;&gt;二、基础语法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%B8%B8%E7%94%A8%E6%89%A9%E5%B1%95%E8%AF%AD%E6%B3%95&quot;&gt;三、常用扩展语法&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%AE%9E%E6%88%98%E6%8E%92%E7%89%88%E5%BB%BA%E8%AE%AE&quot;&gt;四、实战排版建议&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98%E4%B8%8E%E6%8E%92%E9%94%99&quot;&gt;五、常见问题与排错&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E9%99%84%E5%BD%95%E9%80%9F%E6%9F%A5%E6%B8%85%E5%8D%95&quot;&gt;六、附录：速查清单&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;准备工作&lt;/h2&gt;
&lt;h3&gt;1. 安装编辑器&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;VS Code 下载地址：
&lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;https://code.visualstudio.com/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;2. 推荐插件&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Markdown All in One：快捷键、目录生成、列表增强。&lt;/li&gt;
&lt;li&gt;Markdown Preview Enhanced：预览增强、数学公式、图表支持。&lt;/li&gt;
&lt;li&gt;Paste Image：快速粘贴图片并自动生成链接。&lt;/li&gt;
&lt;li&gt;Markdown PDF（可选）：导出 PDF，但复杂样式时不一定稳定。&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 基本工作流&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;新建 &lt;code&gt;xxx.md&lt;/code&gt; 文件。&lt;/li&gt;
&lt;li&gt;使用 VS Code 预览：&lt;code&gt;Ctrl+Shift+V&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;左边写作，右边预览，边改边看。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;基础语法&lt;/h2&gt;
&lt;h3&gt;1. 标题&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;# 一级标题
## 二级标题
### 三级标题
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;建议一篇文章只使用一个一级标题，正文从二级标题开始。&lt;/p&gt;
&lt;h3&gt;2. 段落与换行&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;空一行表示新段落。&lt;/li&gt;
&lt;li&gt;行尾加两个空格再回车表示强制换行。&lt;/li&gt;
&lt;li&gt;分割线常用 &lt;code&gt;---&lt;/code&gt; 或 &lt;code&gt;***&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h3&gt;3. 引用&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;&amp;gt; 一级引用
&amp;gt;&amp;gt; 二级引用
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;示例：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这是一级引用。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;这是二级引用。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/blockquote&gt;
&lt;h3&gt;4. 列表&lt;/h3&gt;
&lt;p&gt;无序列表可用 &lt;code&gt;-&lt;/code&gt;、&lt;code&gt;*&lt;/code&gt;、&lt;code&gt;+&lt;/code&gt;，建议统一一种风格：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- 列表项 A
- 列表项 B
  - 子项 B1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有序列表：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;1. 第一步
2. 第二步
3. 第三步
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;任务列表（Todo）：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;- [x] 已完成
- [ ] 未完成
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;5. 文本强调&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;效果&lt;/th&gt;
&lt;th&gt;语法&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;斜体&lt;/td&gt;
&lt;td&gt;&lt;code&gt;*斜体*&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;粗体&lt;/td&gt;
&lt;td&gt;&lt;code&gt;**粗体**&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;粗斜体&lt;/td&gt;
&lt;td&gt;&lt;code&gt;***粗斜体***&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;删除线&lt;/td&gt;
&lt;td&gt;&lt;code&gt;~~删除线~~&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;行内代码&lt;/td&gt;
&lt;td&gt;&lt;code&gt;`code`&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;说明：&lt;code&gt;&amp;lt;u&amp;gt;下划线&amp;lt;/u&amp;gt;&lt;/code&gt; 这类 HTML 标签也可用，但不同平台兼容性略有差异。&lt;/p&gt;
&lt;h3&gt;6. 代码块&lt;/h3&gt;
&lt;p&gt;建议给代码块加语言标识，方便高亮：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;iostream&amp;gt;
using namespace std;

int main() {
  cout &amp;lt;&amp;lt; &quot;hello world&quot; &amp;lt;&amp;lt; endl;
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;行内代码示例：&lt;code&gt;print(&quot;hello world&quot;);&lt;/code&gt;&lt;/p&gt;
&lt;h3&gt;7. 表格&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;| 左对齐 | 居中对齐 | 右对齐 |
| :-- | :--: | --: |
| a | b | c |
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;8. 链接与图片&lt;/h3&gt;
&lt;p&gt;行内链接：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Markdown 教程](https://www.runoob.com/markdown/md-tutorial.html)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;引用式链接：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;查看更多请看[教程][md-guide]

[md-guide]: https://www.runoob.com/markdown/md-tutorial.html
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;图片：&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;![图片说明](https://example.com/demo.png)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可点击放大图：&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://imgse.com/i/pFZHwAe&quot;&gt;&lt;img src=&quot;https://s11.ax1x.com/2024/01/23/pFZHwAe.jpg&quot; alt=&quot;pFZHwAe.jpg&quot; /&gt;&lt;/a&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;常用扩展语法&lt;/h2&gt;
&lt;h3&gt;1. 数学公式（LaTeX）&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;行内公式：$f(x)=ax+b$&lt;/li&gt;
&lt;li&gt;块级公式：&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;$$
\begin{Bmatrix}
a &amp;amp; b \
c &amp;amp; d
\end{Bmatrix}
$$&lt;/p&gt;
&lt;h3&gt;2. HTML 混写&lt;/h3&gt;
&lt;p&gt;Markdown 中可以直接写 HTML，例如居中图片：&lt;/p&gt;
&lt;p&gt;&amp;lt;div align=&quot;center&quot;&amp;gt;
&amp;lt;a href=&quot;https://imgse.com/i/pFZHwAe&quot;&amp;gt;
&amp;lt;img src=&quot;https://s11.ax1x.com/2024/01/23/pFZHwAe.jpg&quot; alt=&quot;pFZHwAe.jpg&quot; width=&quot;60%&quot; /&amp;gt;
&amp;lt;/a&amp;gt;
&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;适用场景：Markdown 语法不够表达时，用 HTML 补充。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;实战排版建议&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;每个二级标题聚焦一个主题，控制段落长度。&lt;/li&gt;
&lt;li&gt;代码块都标语言，避免“纯文本代码”。&lt;/li&gt;
&lt;li&gt;列表缩进统一 2 或 4 空格，不要混用。&lt;/li&gt;
&lt;li&gt;链接文案要有语义，不要只写“点这里”。&lt;/li&gt;
&lt;li&gt;图片加 &lt;code&gt;alt&lt;/code&gt;，便于可访问性和 SEO。&lt;/li&gt;
&lt;/ol&gt;
&lt;hr /&gt;
&lt;h2&gt;常见问题与排错&lt;/h2&gt;
&lt;h3&gt;1. 目录点击不跳转&lt;/h3&gt;
&lt;p&gt;原因：标题锚点与目录链接不一致。&lt;br /&gt;
建议：先确定标题文本，再复制自动生成的锚点。&lt;/p&gt;
&lt;h3&gt;2. 表格错位&lt;/h3&gt;
&lt;p&gt;原因：中英文字符宽度混合、列数不一致。&lt;br /&gt;
建议：先保证每行列数一致，再调整对齐符号。&lt;/p&gt;
&lt;h3&gt;3. 代码不高亮&lt;/h3&gt;
&lt;p&gt;原因：代码块没写语言标识。&lt;br /&gt;
建议：把 &lt;code&gt;改为&lt;/code&gt;js、&lt;code&gt;cpp、&lt;/code&gt;bash 等。&lt;/p&gt;
&lt;h3&gt;4. 公式不渲染&lt;/h3&gt;
&lt;p&gt;原因：预览器或站点未启用数学插件。&lt;br /&gt;
建议：确认你的 Markdown 渲染环境支持 KaTeX/MathJax。&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;附录速查清单&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;# 标题
## 二级标题

**粗体** *斜体* ~~删除线~~

&amp;gt; 引用

- 无序列表
1. 有序列表
- [ ] 任务项

`行内代码`

```js
console.log(&apos;code block&apos;)
```

[链接](https://example.com)
![图片](https://example.com/a.png)

$E=mc^2$
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你刚开始写博客，建议先按“基础语法 + 实战排版建议”这两节执行，先形成稳定写作模板，再逐步加高级语法。&lt;/p&gt;
</content:encoded></item></channel></rss>