Files
App.K12.Student.Miniapp_Flu…/lib/pages/demo/align_demo.dart
T
2026-09-04 15:22:20 +08:00

97 lines
4.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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),
),
],
),
),
),
),
);
}
}