在这里插入图片描述

收藏夹是艺考学习应用中的核心功能模块,其核心价值在于帮助用户沉淀高频考点、易错题目,提升复习效率。本次实现的收藏夹页面围绕「易用性、可视化、可管理」三大设计原则,涵盖收藏统计、分类筛选、排序、空状态引导等全场景功能,适配OpenHarmony系统的交互规范与UI风格。

收藏夹架构设计

收藏夹页面需动态响应收藏数据的增删改操作,因此选择StatefulWidget作为基础组件,核心设计要点:

  • 状态管理:通过State类维护核心数据,保证操作后UI实时刷新
  • 生命周期:在initState中初始化数据,避免页面加载空白
  • 数据解耦:收藏列表与排序类型分离,便于后续功能扩展
class FavoriteQuestionsPage extends StatefulWidget {
  const FavoriteQuestionsPage({Key? key}) : super(key: key);

  
  State<FavoriteQuestionsPage> createState() => 
      _FavoriteQuestionsPageState();
}

定义页面状态类,聚焦核心数据管理,设计考量如下:

  • 核心字段:仅保留收藏列表和排序类型,降低状态复杂度
  • 初始化逻辑:页面创建时自动加载收藏数据,保证数据时效性
class _FavoriteQuestionsPageState extends State<FavoriteQuestionsPage> {
  List<Question> favoriteQuestions = [];
  String sortType = 'time'; // time/ difficulty/ category

  
  void initState() {
    super.initState();
    _loadFavoriteQuestions();
  }
}

收藏数据加载

收藏数据加载需兼顾本地缓存与云端同步,演示阶段采用模拟数据,核心设计要点:

  • 数据来源:实际项目中需关联用户账户,支持跨设备同步
  • 性能优化:异步加载数据,避免阻塞UI线程
  • 数据过滤:加载时剔除失效题目,保证数据有效性
void _loadFavoriteQuestions() {
  // 模拟加载:取前3条作为收藏数据
  final allQuestions = MockData.getQuestions();
  favoriteQuestions = allQuestions.take(3).toList();
}

空状态界面

空状态是提升用户体验的关键环节,设计时需注意:

  • 视觉引导:大尺寸图标+分层文字,清晰传递无收藏状态
  • 操作指引:明确告知收藏触发方式,降低用户学习成本
  • 风格统一:适配OpenHarmony中性色规范,保持视觉一致性
Widget _buildEmptyState() {
  return Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(Icons.star_border, size: 100.w, color: Colors.grey[400]),
        SizedBox(height: 16.h),
        Text('暂无收藏题目', style: TextStyle(fontSize: 18.sp)),
      ],
    ),
  );
}

补充空状态的引导文案,强化操作指引:

  • 二级提示:明确收藏操作路径,引导用户完成首次收藏
  • 间距控制:通过SizedBox保证元素间距,符合移动端交互习惯
        SizedBox(height: 8.h),
        Text(
          '在答题时点击收藏按钮即可收藏',
          style: TextStyle(fontSize: 14.sp, color: Colors.grey[500]),
        ),
      ],
    ),
  );
}

收藏统计功能

收藏统计模块帮助用户快速掌握收藏数据分布,设计要点:

  • 视觉区分:浅橙色容器突出统计区域,不抢夺核心内容焦点
  • 布局适配:Wrap组件实现标签流式布局,适配不同屏幕宽度
  • 数据维度:按分类统计数量,帮助用户定位高频复习方向
Widget _buildStatistics() {
  final categoryStats = _getCategoryStatistics();
  return Container(
    margin: EdgeInsets.all(16.w),
    padding: EdgeInsets.all(16.w),
    decoration: BoxDecoration(
      color: Colors.orange[50],
      borderRadius: BorderRadius.circular(12.r),
    ),
    child: Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text('收藏统计', style: TextStyle(fontSize: 16.sp, fontWeight: FontWeight.bold)),
        SizedBox(height: 12.h),

统计标签的展示逻辑,优化交互体验:

  • 样式设计:浅橙色背景+圆角,符合移动端标签设计趋势
  • 信息传递:分类名称+数量组合,直观展示统计结果
  • 间距控制:保证标签间呼吸感,避免视觉拥挤
        Wrap(
          spacing: 8.w,
          runSpacing: 8.h,
          children: categoryStats.entries.map((entry) {
            return Container(
              padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 6.h),
              decoration: BoxDecoration(
                color: Colors.orange[100],
                borderRadius: BorderRadius.circular(16.r),
              ),
              child: Text('${entry.key}: ${entry.value}'),
            );
          }).toList(),
        ),
      ],
    ),
  );
}

分类统计实现

分类统计的核心是遍历收藏列表完成计数,设计要点:

  • 数据结构:Map存储分类-数量键值对,查询效率高
  • 空值处理:??运算符避免首次统计时的空指针异常
  • 逻辑简洁:遍历累加,保证统计逻辑易理解、易维护
Map<String, int> _getCategoryStatistics() {
  final Map<String, int> stats = {};
  for (final question in favoriteQuestions) {
    stats[question.category] = (stats[question.category] ?? 0) + 1;
  }
  return stats;
}

收藏列表实现

收藏列表采用ListView.builder实现懒加载,核心设计:

  • 性能优化:仅渲染可见区域卡片,降低内存占用
  • 结构分层:先展示统计模块,再展示列表,符合用户认知习惯
  • 卡片容器:Card组件包裹内容,提升视觉层次感
Widget _buildFavoriteList() {
  return Column(
    children: [
      _buildStatistics(),
      Expanded(
        child: ListView.builder(
          itemCount: favoriteQuestions.length,
          itemBuilder: (context, index) {
            final question = favoriteQuestions[index];
            return Card(
              margin: EdgeInsets.symmetric(horizontal: 16.w, vertical: 8.h),
              child: ListTile(

收藏卡片核心信息展示,兼顾信息密度与可读性:

  • 左侧标识:圆形头像+星星图标,直观标记收藏状态
  • 标题处理:限制行数+文字截断,避免标题过长错乱
  • 副标题分层:展示分类、科目,满足快速筛选需求
                leading: CircleAvatar(
                  backgroundColor: Colors.orange[100],
                  child: Icon(Icons.star, color: Colors.orange[600]),
                ),
                title: Text(
                  question.title,
                  style: TextStyle(fontSize: 16.sp),
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                ),
                subtitle: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Text('${question.category} - ${question.subject}'),

收藏卡片辅助信息展示,丰富数据维度:

  • 难度标记:通过Chip组件可视化展示题目难度
  • 时间信息:年份+收藏时间,帮助用户回忆收藏场景
  • 间距控制:合理留白,提升信息可读性
                    Row(
                      children: [
                        _buildDifficultyChip(question.difficulty),
                        SizedBox(width: 8.w),
                        Text('${question.year}年'),
                        SizedBox(width: 8.w),
                        Text('收藏于 ${_getFavoriteTime(index)}'),
                      ],
                    ),
                  ],
                ),

收藏卡片快捷操作按钮,优化操作路径:

  • 轻量化设计:仅展示图标,节省页面空间
  • 功能直达:练习、取消收藏按钮,满足高频操作需求
  • 路由跳转:点击卡片/按钮跳转对应页面,逻辑清晰
                trailing: Row(
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    IconButton(
                      icon: const Icon(Icons.play_arrow),
                      onPressed: () {
                        Navigator.pushNamed(context, '/exam', arguments: '收藏练习');
                      },
                    ),
                    IconButton(
                      icon: const Icon(Icons.star),
                      onPressed: () => _removeFavorite(question.id),
                    ),
                  ],
                ),
                onTap: () => Navigator.pushNamed(context, '/question_detail', arguments: question),
              ),
            );
          },
        ),
      ),
    ],
  );
}

排序功能实现

排序功能入口设计在AppBar,符合移动端操作习惯:

  • 入口位置:AppBar右侧,易发现、易操作
  • 选项设计:覆盖时间、难度、分类三大核心排序维度
  • 状态同步:选择后立即更新状态并触发排序
actions: [
  PopupMenuButton<String>(
    onSelected: (value) {
      setState(() {
        sortType = value;
        _sortQuestions();
      });
    },
    itemBuilder: (context) => [
      const PopupMenuItem(value: 'time', child: Text('按时间排序')),
      const PopupMenuItem(value: 'difficulty', child: Text('按难度排序')),
      const PopupMenuItem(value: 'category', child: Text('按分类排序')),
    ],
  ),
],

排序逻辑实现

排序逻辑根据不同维度定制比较规则,设计要点:

  • 维度适配:不同排序类型对应不同比较逻辑
  • 难度排序:自定义优先级(简单<中等<困难),符合用户认知
  • 即时刷新:setState触发UI重建,排序结果实时展示
void _sortQuestions() {
  setState(() {
    switch (sortType) {
      case 'time':
        favoriteQuestions.sort((a, b) => a.id.compareTo(b.id));
        break;
      case 'difficulty':
        final order = {'简单': 1, '中等': 2, '困难': 3};
        favoriteQuestions.sort((a, b) => order[a.difficulty]!.compareTo(order[b.difficulty]!));
        break;
      case 'category':
        favoriteQuestions.sort((a, b) => a.category.compareTo(b.category));
        break;
    }
  });
}

收藏时间显示

收藏时间采用相对时间展示,提升用户体验:

  • 友好性:「X天前」比绝对时间更符合阅读习惯
  • 模拟数据:演示阶段用索引模拟,实际需存储真实时间戳
  • 本地化:适配OpenHarmony本地化API,兼容多语言
String _getFavoriteTime(int index) {
  // 模拟收藏时间:索引*2+1天前
  final days = index * 2 + 1;
  return '${days}天前';
}

取消收藏功能

取消收藏需保证操作安全且反馈及时,设计要点:

  • 数据更新:移除对应题目,保证列表数据一致性
  • 视觉反馈:SnackBar提示操作结果,提升用户感知
  • 防误操作:可扩展确认弹窗,降低误操作概率
void _removeFavorite(String questionId) {
  setState(() {
    favoriteQuestions.removeWhere((q) => q.id == questionId);
  });
  ScaffoldMessenger.of(context).showSnackBar(
    const SnackBar(content: Text('已取消收藏')),
  );
}

用户体验优化

为了提升用户体验,我们在收藏卡片上添加了快捷操作按钮。用户可以直接点击练习按钮进入收藏题目练习,或者点击星标按钮取消收藏。

数据持久化考虑

在实际应用中,收藏数据需要持久化存储。我们可以使用SharedPreferences或数据库来存储收藏信息,确保数据不会丢失。

性能优化

收藏列表使用ListView.builder来优化性能,确保只有可见的收藏题目会被渲染。同时,我们使用const构造函数减少不必要的重建。

通过以上实现,我们创建了一个功能完善、用户友好的收藏夹页面。这个页面不仅能够帮助用户管理收藏题目,还提供了丰富的统计信息和排序功能,为用户的学习提供了便利。

欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐