flutter架 构项目基础

This commit is contained in:
崔宝新
2026-09-04 15:22:20 +08:00
parent 70967229d0
commit 0c5aee59c0
265 changed files with 35484 additions and 0 deletions
+238
View File
@@ -0,0 +1,238 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/// ============================================================
/// Text 文本组件各种细节演示页
///
/// 一、两种使用方式:
/// 1. 直接运行本页面:runApp(const MaterialApp(home: TextDemoPage()))
/// 2. 复制某段核心代码到任意 Scaffold 的 body 中。
///
/// 二、Text 全家桶速记:
/// 单样式文字 → Text
/// 富文本拼接 → Text.rich + TextSpan
/// 全局默认样式 → DefaultTextStyle(MaterialApp 自带,Text 会继承)
///
/// 三、Flutter 3.x 注意:
/// textScaleFactor 已废弃 → 用 textScaler / MediaQuery.textScalerOf(context)
/// 颜色的 withOpacity 已废弃 → 用 withValues(alpha: x)
/// ============================================================
class TextDemoPage extends StatelessWidget {
const TextDemoPage({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Text 文本组件 Demo'), backgroundColor: Colors.blue),
body: SingleChildScrollView(
padding: EdgeInsets.all(16.w),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const _SectionTitle('1. 基础样式:fontSize / color / fontWeight / fontStyle'),
Text(
'默认样式',
style: TextStyle(fontSize: 16.sp),
),
SizedBox(height: 8.h),
Text(
'加粗 红色 斜体',
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
color: Color(0xFFE53935),
fontStyle: FontStyle.italic,
),
),
SizedBox(height: 24.h),
const _SectionTitle('2. 对齐 textAlign(需有宽度约束)'),
Container(
width: 300.w,
color: const Color(0xFFF5F7FA),
child: const Column(
// 关键:stretch 让每个子组件横向拉满,textAlign 才有空间生效
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text('左对齐', textAlign: TextAlign.left),
Text('居中对齐', textAlign: TextAlign.center),
Text('右对齐', textAlign: TextAlign.right),
],
),
),
SizedBox(height: 24.h),
const _SectionTitle('3. 截断:maxLines + overflow(三件套必须配齐)'),
// 要点:Text 必须有【有界宽度】溢出才生效,所以外面套了固定宽的 Container
Container(
width: 300.w,
color: const Color(0xFFF5F7FA),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'ellipsis:这是一段非常非常非常长的文字,用来演示溢出省略号的效果,看看能不能截断显示',
maxLines: 1,
overflow: TextOverflow.ellipsis, // 末尾加省略号
),
SizedBox(height: 8.h),
Text(
'clip:这是一段非常非常非常长的文字,用来演示溢出直接裁剪的效果,看看能不能截断显示',
maxLines: 1,
overflow: TextOverflow.clip, // 直接裁掉,不加省略号
),
SizedBox(height: 8.h),
Text(
// visible:文字真·溢出,直接画出灰色盒子边界(Container 默认不裁剪)
'softWrap:false:文字横向溢出灰色盒子边界,直接画到盒子外面去',
softWrap: false, // 禁止自动换行
overflow: TextOverflow.visible,
),
],
),
),
SizedBox(height: 24.h),
const _SectionTitle('4. 行高 height(对比默认行高)'),
Container(
width: 300.w,
color: const Color(0xFFF5F7FA),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'默认行高\n第二行内容',
style: TextStyle(fontSize: 16.sp),
),
SizedBox(height: 8.h),
Text(
'height:1.2 紧凑\n第二行内容',
style: TextStyle(fontSize: 16.sp, height: 1.2),
),
SizedBox(height: 8.h),
Text(
'height:2 松散\n第二行内容',
style: TextStyle(fontSize: 16.sp, height: 2),
),
],
),
),
SizedBox(height: 24.h),
const _SectionTitle('5. 字间距 letterSpacing / 词间距 wordSpacing'),
Text(
'字间距 4:Flutter 框架真棒',
style: TextStyle(fontSize: 16.sp, letterSpacing: 4),
),
SizedBox(height: 8.h),
Text(
'词间距 8:Flutter Framework Great',
style: TextStyle(fontSize: 16.sp, wordSpacing: 8),
),
SizedBox(height: 24.h),
const _SectionTitle('6. 富文本:Text.rich + TextSpan'),
// 正确写法:recognizer 放 StatefulWidget 里创建并 dispose
const _AgreementRichText(),
SizedBox(height: 24.h),
const _SectionTitle('7. 字体缩放 textScaler(Flutter 3 新写法)'),
// 旧写法 textScaleFactor 已废弃;textScaler 按倍数放大
Text(
'线性放大 1.5 倍',
style: TextStyle(fontSize: 14.sp),
textScaler: TextScaler.linear(1.5),
),
SizedBox(height: 8.h),
// 跟随系统设置:MaterialApp 已按系统字体缩放,也可显式读取
Builder(
builder: (context) {
final ts = MediaQuery.textScalerOf(context);
return Text(
'当前系统缩放:${ts.scale(14).toStringAsFixed(1)}px(原本14px)',
style: TextStyle(fontSize: 14.sp),
);
},
),
],
),
),
);
}
}
/// 区块标题
class _SectionTitle extends StatelessWidget {
const _SectionTitle(this.title);
final String title;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(bottom: 12.h),
child: Text(
title,
style: TextStyle(
fontSize: 16.sp,
fontWeight: FontWeight.bold,
color: Color(0xFF333333),
),
),
);
}
}
/// 富文本协议段落 —— StatefulWidget 版本
/// 关键点:TapGestureRecognizer 必须在 dispose() 里释放,防止内存泄漏
class _AgreementRichText extends StatefulWidget {
const _AgreementRichText();
@override
State<_AgreementRichText> createState() => _AgreementRichTextState();
}
class _AgreementRichTextState extends State<_AgreementRichText> {
// late final:整个 State 生命周期只创建一次,复用同一个 recognizer
late final TapGestureRecognizer _agreementRecognizer = TapGestureRecognizer()
..onTap = _handleAgreementTap;
void _handleAgreementTap() {
// 点击回调可能晚于 dispose(比如点击瞬间页面被切走),用 mounted 兜底
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('点了《用户协议》')),
);
}
@override
void dispose() {
// 关键:释放 recognizer,与 createState 一一对应
_agreementRecognizer.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Text.rich(
TextSpan(
children: [
TextSpan(
text: '已阅读并同意',
style: TextStyle(fontSize: 14.sp, color: Color(0xFF888888)),
),
TextSpan(
text: '《用户协议》',
style: TextStyle(
fontSize: 14.sp,
color: Color(0xFF3B82F6),
fontWeight: FontWeight.bold,
),
recognizer: _agreementRecognizer,
),
],
),
);
}
}