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
+96
View File
@@ -0,0 +1,96 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:new_learn/core/providers/user_provider.dart';
/// ============================================================
/// Align 对齐布局演示页 + Riverpod 全局用户信息展示
///
/// 一、Align 两种使用方式:
/// 1. 直接运行本页面:把 main() 改为
/// runApp(const ProviderScope(child: MaterialApp(home: AlignDemoPage())));
/// 2. 复制 body 核心代码到任意 Scaffold 的 body 中:
///
/// body: Container(
/// width: 300,
/// height: 300,
/// color: Colors.grey[200],
/// child: Align(
/// alignment: Alignment.bottomLeft, // 子组件放到父盒子左下角
/// child: Container(...), // 用户信息卡片
/// ),
/// ),
///
/// 二、Flutter 核心布局规则(务必理解):
/// 1. 父组件给子组件传递【约束】(Constraints),子组件在约束范围内决定自身【大小】;
/// 2. Align 会把自身区域扩大到父组件允许的最大范围(宽高撑满),
/// 然后通过 alignment 把子组件放到指定位置;
/// 3. 子组件的 size(宽高)如果不写,Align 会取子组件的固有尺寸;
/// 一旦写了固定 width/height,就由子组件自己决定,Align 不再干预。
///
/// 三、Riverpod 全局状态用法(本次新增重点):
/// - AlignDemoPage 改成 ConsumerWidget(build 多一个 WidgetRef ref 参数);
/// - `ref.watch(currentUserProvider)` 订阅全局用户,登录后任何页面都拿到;
/// - `.value` 是 CurrentUserExtension?:登录了有值,未登录是 null;
/// - 登录页登录成功时会 set 这个 provider,本卡片自动刷新(无需手动 setState)。
///
/// 四、高频坑:
/// 1. 用了 ref 的组件必须继承 ConsumerWidget / ConsumerStatefulWidget,
/// 普通 StatelessWidget 拿不到 ref(编译报错);
/// 2. ref.watch 要在 build 里调用(声明式依赖),ref.read 才能放回调里;
/// 3. 加了 .w/.h/.sp 的 widget 不能再用 const(尺寸是运行期算的)。
/// ============================================================
class AlignDemoPage extends ConsumerWidget {
const AlignDemoPage({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// Riverpod 全局用户:登录后全 App 共享,未登录为 null
final user = ref.watch(currentUserProvider).value;
return Scaffold(
appBar: AppBar(title: const Text('Align 对齐布局 Demo11')),
// ---------- 下方即为核心代码,可直接复制到 Scaffold body ----------
body: Container(
width: 300.w,
height: 300.h,
color: Colors.grey[300],
child: Align(
alignment: Alignment.bottomLeft, // 子组件放到父盒子左下角
child: Container(
width: 240.w,
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 10.h),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(8.w),
),
child: Column(
mainAxisSize: MainAxisSize.min, // 卡片高度跟随内容
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'用户:${user?.userName ?? '未登录'}',
style: TextStyle(
color: Colors.white,
fontSize: 18.sp,
fontWeight: FontWeight.bold,
),
),
SizedBox(height: 6.h),
Text(
'班级:${user?.className ?? '-'}',
style: TextStyle(color: Colors.white, fontSize: 14.sp),
),
SizedBox(height: 4.h),
Text(
'积分:${user?.userPoints ?? 0}',
style: TextStyle(color: Colors.white, fontSize: 14.sp),
),
],
),
),
),
),
);
}
}