flutter_for_openharmony手语学习app实战+个人中心实现

个人中心是用户管理个人信息和访问各项功能的入口。本文介绍如何实现一个功能完善的个人中心页面,包括用户信息展示、统计数据和功能菜单。

页面基础结构

定义个人中心页面:

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创建线性渐变,从深色到浅色。默认方向是从左到右,也可以通过beginend参数自定义方向。渐变色比纯色更有层次感,让用户卡片更吸引眼球。

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

相关推荐
子春一2 小时前
Flutter for OpenHarmony:构建一个智能长度单位转换器,深入解析 Flutter 中的多字段联动、输入同步与工程化表单设计
开发语言·javascript·flutter
2601_949613022 小时前
flutter_for_openharmony家庭药箱管理app实战+用药提醒列表实现
服务器·前端·flutter
冰语竹2 小时前
Android学习-随笔(安装后设置路径)
android·学习
芯思路2 小时前
STM32开发学习笔记之七【LCD显示图片】
笔记·stm32·学习
问道飞鱼2 小时前
【大模型学习】提示词工程(Prompt Engineering)技术深度报告
学习·prompt·提示词
hssfscv2 小时前
Javaweb学习笔记——后端实战7 springAOP
笔记·后端·学习
来两个炸鸡腿2 小时前
【Datawhale组队学习202601】Base-NLP task06 大模型训练与量化
人工智能·学习·自然语言处理
bylander2 小时前
【AI学习】TM Forum自智网络L4级标准体系
人工智能·学习·智能体·自动驾驶网络
我想我不够好。2 小时前
2026.1.28 消防监控学习
学习