个人中心是用户管理个人信息和访问各项功能的入口。本文介绍如何实现一个功能完善的个人中心页面,包括用户信息展示、统计数据和功能菜单。
页面基础结构
定义个人中心页面:
dart
class ProfileScreen extends StatelessWidget {
const ProfileScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('我的'),
actions: [
IconButton(
icon: const Icon(Icons.settings),
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const SettingsScreen()),
),
),
],
),
使用StatelessWidget构建页面,AppBar右侧放置设置按钮,点击跳转到设置页面。这种快捷入口设计让用户可以快速访问常用功能,无需在菜单中查找。
页面布局
构建整体的滚动布局:
dart
body: SingleChildScrollView(
child: Column(
children: [
_buildUserCard(context),
_buildStatsCard(context),
_buildMenuList(context),
],
),
),
);
}
用SingleChildScrollView包裹,内容过多时可以滚动。Column纵向排列三个区域:用户卡片、统计卡片和功能菜单。这种分区设计让信息层次清晰,用户一眼就能找到想要的功能。
用户卡片
构建顶部的用户信息卡片:
dart
Widget _buildUserCard(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
return Container(
margin: EdgeInsets.all(16.w),
padding: EdgeInsets.all(20.w),
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF00897B), Color(0xFF4DB6AC)],
),
borderRadius: BorderRadius.circular(16.r),
),
从Provider获取用户数据,用渐变色背景和圆角装饰容器。渐变色从深到浅,营造立体感。这种设计让用户卡片成为页面的视觉焦点,突出用户身份。
用户头像和信息
显示头像、昵称和等级:
dart
child: Column(
children: [
Row(
children: [
CircleAvatar(
radius: 40.r,
backgroundColor: Colors.white,
child: Icon(Icons.person, size: 45.sp, color: const Color(0xFF00897B)),
),
SizedBox(width: 16.w),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
userProvider.userName,
style: TextStyle(
fontSize: 22.sp,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
SizedBox(height: 4.h),
头像用CircleAvatar显示为圆形,白色背景配主题色图标。昵称用大字号粗体白色显示,在渐变背景上清晰可读。Expanded让信息区域占据剩余空间,确保布局不会因昵称长度变化而错乱。
等级标签
显示用户等级和身份:
dart
Container(
padding: EdgeInsets.symmetric(horizontal: 8.w, vertical: 2.h),
decoration: BoxDecoration(
color: Colors.white.withOpacity(0.2),
borderRadius: BorderRadius.circular(12.r),
),
child: Text(
'Lv.${userProvider.level} 手语学习者',
style: TextStyle(fontSize: 12.sp, color: Colors.white),
),
),
],
),
),
等级标签用半透明白色背景和圆角,文字也是白色。这种玻璃态设计在渐变背景上很有质感。等级数字动态显示,随着用户学习进度提升而变化。
编辑按钮
右侧放置编辑图标:
dart
IconButton(
icon: const Icon(Icons.edit, color: Colors.white),
onPressed: () => _showEditNameDialog(context, userProvider),
),
],
),
SizedBox(height: 16.h),
编辑按钮用白色图标,与背景形成对比。点击弹出对话框修改昵称,这种就地编辑的交互方式简单直观。按钮放在右侧,符合用户操作习惯。
经验值进度条
显示升级进度:
dart
LinearPercentIndicator(
lineHeight: 8.h,
percent: userProvider.levelProgress,
backgroundColor: Colors.white.withOpacity(0.3),
progressColor: Colors.white,
barRadius: Radius.circular(4.r),
),
SizedBox(height: 8.h),
用线性进度条显示当前等级的经验值进度,背景用半透明白色,进度用纯白色。在渐变背景上,白色进度条非常醒目。进度条让用户清楚距离下一级还有多远,激励继续学习。
经验值文字
显示具体的经验值数据:
dart
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
'经验值: ${userProvider.experience}',
style: TextStyle(fontSize: 12.sp, color: Colors.white70),
),
Text(
'距下一级还需: ${userProvider.experienceToNextLevel}',
style: TextStyle(fontSize: 12.sp, color: Colors.white70),
),
],
),
],
),
);
}
左右两端显示当前经验值和升级所需经验值,用半透明白色文字。mainAxisAlignment.spaceBetween让文字分布在两端,充分利用空间。这种数据展示让用户了解详细的升级进度。
统计卡片
构建统计数据展示:
dart
Widget _buildStatsCard(BuildContext context) {
final userProvider = Provider.of<UserProvider>(context);
final appProvider = Provider.of<AppProvider>(context);
return Card(
margin: EdgeInsets.symmetric(horizontal: 16.w),
child: Padding(
padding: EdgeInsets.all(16.w),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
_buildStatItem('连续学习', '${userProvider.consecutiveDays}天', Icons.local_fire_department, Colors.orange),
_buildStatItem('已学词汇', '${appProvider.completedLessons.length}个', Icons.school, Colors.blue),
_buildStatItem('总积分', '${appProvider.totalPoints}', Icons.star, Colors.amber),
_buildStatItem('成就', '${userProvider.achievements.where((a) => a.isUnlocked).length}个', Icons.emoji_events, Colors.purple),
],
),
),
);
}
从两个Provider获取统计数据,用Row横向排列四个统计项。mainAxisAlignment.spaceAround让它们均匀分布。每个统计项包含图标、数值和标签,调用_buildStatItem方法构建。这种数据可视化让用户快速了解学习成果。
统计项构建
封装统计项的构建逻辑:
dart
Widget _buildStatItem(String label, String value, IconData icon, Color color) {
return Column(
children: [
Icon(icon, color: color, size: 28.sp),
SizedBox(height: 8.h),
Text(value, style: TextStyle(fontSize: 18.sp, fontWeight: FontWeight.bold)),
Text(label, style: TextStyle(fontSize: 11.sp, color: Colors.grey)),
],
);
}
用Column纵向排列图标、数值和标签。图标用不同颜色区分:火焰橙色代表连续学习,书本蓝色代表词汇,星星金色代表积分,奖杯紫色代表成就。数值用大字号粗体,标签用小字号灰色。这种颜色语义化让统计项更生动。
功能菜单
构建功能入口列表:
dart
Widget _buildMenuList(BuildContext context) {
final menuItems = [
{'icon': Icons.bookmark, 'title': '我的收藏', 'screen': const FavoritesScreen()},
{'icon': Icons.emoji_events, 'title': '成就徽章', 'screen': const AchievementScreen()},
{'icon': Icons.bar_chart, 'title': '学习统计', 'screen': const StatisticsScreen()},
{'icon': Icons.feedback, 'title': '意见反馈', 'screen': const FeedbackScreen()},
{'icon': Icons.info, 'title': '关于我们', 'screen': const AboutScreen()},
];
定义5个菜单项,每个包含图标、标题和目标页面。图标语义化:书签代表收藏,奖杯代表成就,柱状图代表统计,反馈图标代表意见,信息图标代表关于。这种数据驱动的方式便于添加或删除菜单项。
菜单列表
使用map生成菜单项:
dart
return Card(
margin: EdgeInsets.all(16.w),
child: Column(
children: menuItems.map((item) {
return ListTile(
leading: Icon(item['icon'] as IconData, color: const Color(0xFF00897B)),
title: Text(item['title'] as String),
trailing: const Icon(Icons.chevron_right),
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => item['screen'] as Widget),
),
);
}).toList(),
),
);
}
用map遍历菜单项生成ListTile,左侧显示主题色图标,中间显示标题,右侧显示箭头。点击跳转到对应页面。这种列表菜单是移动应用的经典设计,用户熟悉这种交互方式。
编辑昵称对话框
弹出对话框修改昵称:
dart
void _showEditNameDialog(BuildContext context, UserProvider userProvider) {
final controller = TextEditingController(text: userProvider.userName);
showDialog(
context: context,
builder: (context) => AlertDialog(
title: const Text('修改昵称'),
content: TextField(
controller: controller,
decoration: const InputDecoration(hintText: '请输入新昵称'),
),
创建TextEditingController并初始化为当前昵称,用户可以在此基础上修改。TextField提供输入框,hintText提示用户输入内容。这种对话框编辑的方式不会跳转页面,保持上下文连续性。
对话框按钮
确认和取消按钮:
dart
actions: [
TextButton(onPressed: () => Navigator.pop(context), child: const Text('取消')),
ElevatedButton(
onPressed: () {
if (controller.text.isNotEmpty) {
userProvider.setUserName(controller.text);
Navigator.pop(context);
}
},
child: const Text('确定'),
),
],
),
);
}
}
取消按钮用TextButton样式,确定按钮用ElevatedButton样式,视觉上更突出。点击确定前检查输入是否为空,非空才调用Provider更新昵称并关闭对话框。这种输入验证避免了无效数据。
LinearGradient渐变
创建渐变背景:
dart
decoration: BoxDecoration(
gradient: const LinearGradient(
colors: [Color(0xFF00897B), Color(0xFF4DB6AC)],
),
borderRadius: BorderRadius.circular(16.r),
),
LinearGradient创建线性渐变,从深色到浅色。默认方向是从左到右,也可以通过begin和end参数自定义方向。渐变色比纯色更有层次感,让用户卡片更吸引眼球。
Provider的多数据源
从多个Provider获取数据:
dart
final userProvider = Provider.of<UserProvider>(context);
final appProvider = Provider.of<AppProvider>(context);
UserProvider管理用户相关数据如昵称、等级、经验值,AppProvider管理应用全局数据如完成的课程、总积分。分离关注点让代码更模块化,每个Provider只负责自己的领域。
动态数据展示
根据Provider数据动态显示:
dart
Text(userProvider.userName, ...),
Text('Lv.${userProvider.level} 手语学习者', ...),
percent: userProvider.levelProgress,
Text('${userProvider.consecutiveDays}天', ...),
所有显示的数据都来自Provider,当Provider中的数据变化时,界面自动更新。这种响应式编程让数据与UI保持同步,无需手动刷新。
条件计算
计算已解锁成就数量:
dart
'${userProvider.achievements.where((a) => a.isUnlocked).length}个'
使用where方法过滤出已解锁的成就,length获取数量。这种链式调用简洁高效,一行代码完成过滤和计数。Dart的集合操作方法让数据处理更优雅。
图标的语义化
使用与功能相关的图标:
dart
Icons.bookmark, // 收藏
Icons.emoji_events, // 成就
Icons.bar_chart, // 统计
Icons.feedback, // 反馈
Icons.info, // 关于
Icons.local_fire_department, // 连续学习(火焰)
Icons.school, // 词汇(学校)
Icons.star, // 积分(星星)
图标选择要符合功能含义,让用户一眼就能识别。火焰代表连续学习的热情,星星代表积分的价值,奖杯代表成就的荣耀。图标语义化减少用户的认知负担。
颜色的多样性
不同统计项使用不同颜色:
dart
Colors.orange, // 连续学习
Colors.blue, // 已学词汇
Colors.amber, // 总积分
Colors.purple, // 成就
橙色、蓝色、金色、紫色,四种颜色让统计卡片更丰富多彩。颜色选择要有一定的区分度,避免相近颜色混淆。丰富的颜色让界面更生动有趣。
TextEditingController的使用
管理输入框内容:
dart
final controller = TextEditingController(text: userProvider.userName);
TextField(controller: controller, ...),
if (controller.text.isNotEmpty) {
userProvider.setUserName(controller.text);
}
TextEditingController管理输入框的文本内容,可以获取和设置文本。初始化时传入当前昵称,用户可以在此基础上修改。通过controller.text获取输入内容,这是Flutter中管理表单输入的标准方式。
响应式布局
使用flutter_screenutil适配屏幕:
dart
radius: 40.r,
fontSize: 22.sp,
padding: EdgeInsets.all(20.w),
margin: EdgeInsets.all(16.w),
.r用于圆角半径,.sp用于字号,.w和.h用于尺寸和间距。这些单位会根据屏幕尺寸自动缩放,确保在不同设备上比例一致。一套代码适配所有屏幕。
小结
个人中心页面通过渐变色用户卡片展示个人信息和等级进度,统计卡片显示关键数据指标。功能菜单提供各项功能的快捷入口,编辑对话框支持修改昵称。整体设计注重视觉吸引力和功能可达性,打造完善的个人中心体验。
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net