Flutter 框架跨平台鸿蒙开发 - 阅读进度追踪应用开发指南

Flutter实战:阅读进度追踪应用开发指南

前言

阅读进度追踪是一款帮助读者管理阅读计划、记录阅读进度的实用应用。这个项目涵盖了数据建模、状态管理、数据持久化、统计分析等核心技术,是学习Flutter应用开发的优秀实践案例。

效果预览



应用特性:

  • 书籍分类管理(在读/已完成/想读)
  • 阅读进度追踪
  • 阅读统计分析
  • 评分和笔记功能
  • 数据本地持久化

技术架构

业务层
数据层
UI层
TabBar分类
书籍列表
详情页面
进度编辑
Book模型
SharedPreferences
JSON序列化
进度计算
统计分析
状态管理
数据更新

核心数据模型

书籍状态枚举

dart 复制代码
enum BookStatus {
  reading,    // 在读
  completed,  // 已完成
  wishlist,   // 想读
}

书籍模型

dart 复制代码
class Book {
  String id;
  String title;
  String author;
  int totalPages;
  int currentPage;
  BookStatus status;
  DateTime startDate;
  DateTime? finishDate;
  String? notes;
  int rating; // 0-5星

  Book({
    required this.id,
    required this.title,
    required this.author,
    required this.totalPages,
    this.currentPage = 0,
    this.status = BookStatus.wishlist,
    DateTime? startDate,
    this.finishDate,
    this.notes,
    this.rating = 0,
  }) : startDate = startDate ?? DateTime.now();

  // 计算属性
  double get progress => totalPages > 0 ? currentPage / totalPages : 0;
  int get remainingPages => totalPages - currentPage;
  int get readingDays => DateTime.now().difference(startDate).inDays + 1;
  double get averagePagesPerDay => readingDays > 0 ? currentPage / readingDays : 0;
}

统计计算

进度百分比

Progress=CurrentPageTotalPages×100%Progress = \frac{CurrentPage}{TotalPages} \times 100\%Progress=TotalPagesCurrentPage×100%

dart 复制代码
double get progress => totalPages > 0 ? currentPage / totalPages : 0;

平均阅读速度

AverageSpeed=CurrentPageReadingDaysAverageSpeed = \frac{CurrentPage}{ReadingDays}AverageSpeed=ReadingDaysCurrentPage

dart 复制代码
double get averagePagesPerDay => readingDays > 0 ? currentPage / readingDays : 0;

预计完成时间

EstimatedDays=RemainingPagesAverageSpeedEstimatedDays = \frac{RemainingPages}{AverageSpeed}EstimatedDays=AverageSpeedRemainingPages

dart 复制代码
int estimatedDaysToFinish = (remainingPages / averagePagesPerDay).ceil();

数据持久化

JSON序列化

dart 复制代码
class Book {
  Map<String, dynamic> toJson() => {
        'id': id,
        'title': title,
        'author': author,
        'totalPages': totalPages,
        'currentPage': currentPage,
        'status': status.index,
        'startDate': startDate.toIso8601String(),
        'finishDate': finishDate?.toIso8601String(),
        'notes': notes,
        'rating': rating,
      };

  factory Book.fromJson(Map<String, dynamic> json) => Book(
        id: json['id'],
        title: json['title'],
        author: json['author'],
        totalPages: json['totalPages'],
        currentPage: json['currentPage'] ?? 0,
        status: BookStatus.values[json['status'] ?? 0],
        startDate: DateTime.parse(json['startDate']),
        finishDate: json['finishDate'] != null
            ? DateTime.parse(json['finishDate'])
            : null,
        notes: json['notes'],
        rating: json['rating'] ?? 0,
      );
}

SharedPreferences存储

dart 复制代码
Future<void> _saveBooks() async {
  final prefs = await SharedPreferences.getInstance();
  final booksJson = jsonEncode(_books.map((e) => e.toJson()).toList());
  await prefs.setString('books', booksJson);
}

Future<void> _loadBooks() async {
  final prefs = await SharedPreferences.getInstance();
  final booksJson = prefs.getString('books');

  if (booksJson != null) {
    final List<dynamic> list = jsonDecode(booksJson);
    setState(() {
      _books = list.map((e) => Book.fromJson(e)).toList();
    });
  }
}

TabBar分类管理

三标签布局

dart 复制代码
TabBar(
  controller: _tabController,
  tabs: const [
    Tab(text: '在读'),
    Tab(text: '已完成'),
    Tab(text: '想读'),
  ],
)

TabBarView(
  controller: _tabController,
  children: [
    _buildBookList(BookStatus.reading),
    _buildBookList(BookStatus.completed),
    _buildBookList(BookStatus.wishlist),
  ],
)

状态过滤

dart 复制代码
List<Book> _getBooksByStatus(BookStatus status) {
  return _books.where((book) => book.status == status).toList();
}

书籍卡片设计

卡片布局

dart 复制代码
Widget _buildBookCard(Book book) {
  return Card(
    child: Padding(
      padding: const EdgeInsets.all(16),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          // 标题和作者
          Text(book.title, style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold)),
          Text(book.author, style: TextStyle(color: Colors.grey)),
          
          // 进度条
          if (book.status != BookStatus.wishlist) ...[
            LinearProgressIndicator(
              value: book.progress,
              backgroundColor: Colors.grey.shade200,
              valueColor: AlwaysStoppedAnimation(
                book.status == BookStatus.completed ? Colors.green : Colors.deepOrange,
              ),
            ),
            Text('${book.currentPage} / ${book.totalPages} 页'),
          ],
          
          // 统计信息
          if (book.status == BookStatus.reading) ...[
            Text('已读 ${book.readingDays} 天'),
            Text('平均 ${book.averagePagesPerDay.toStringAsFixed(1)} 页/天'),
          ],
        ],
      ),
    ),
  );
}

进度条颜色

开始阅读
完成
想读
在读 - 橙色
已完成 - 绿色

详情页功能

状态切换

dart 复制代码
SegmentedButton<BookStatus>(
  segments: const [
    ButtonSegment(
      value: BookStatus.wishlist,
      label: Text('想读'),
      icon: Icon(Icons.bookmark_border),
    ),
    ButtonSegment(
      value: BookStatus.reading,
      label: Text('在读'),
      icon: Icon(Icons.menu_book),
    ),
    ButtonSegment(
      value: BookStatus.completed,
      label: Text('完成'),
      icon: Icon(Icons.check_circle),
    ),
  ],
  selected: {_book.status},
  onSelectionChanged: (Set<BookStatus> newSelection) {
    _changeStatus(newSelection.first);
  },
)

进度更新

dart 复制代码
void _updateProgress(int newPage) {
  setState(() {
    _book.currentPage = newPage.clamp(0, _book.totalPages);
    
    // 自动更新状态
    if (_book.currentPage > 0 && _book.status == BookStatus.wishlist) {
      _book.status = BookStatus.reading;
      _book.startDate = DateTime.now();
    }
    
    if (_book.currentPage >= _book.totalPages && 
        _book.status == BookStatus.reading) {
      _book.status = BookStatus.completed;
      _book.finishDate = DateTime.now();
    }
  });
  
  widget.onUpdate(_book);
}

评分系统

dart 复制代码
Row(
  mainAxisAlignment: MainAxisAlignment.center,
  children: List.generate(5, (index) {
    return IconButton(
      icon: Icon(
        index < _book.rating ? Icons.star : Icons.star_border,
        color: Colors.amber,
        size: 36,
      ),
      onPressed: () => _updateRating(index + 1),
    );
  }),
)

阅读统计

统计指标

指标 计算方式 说明
进度 currentPage / totalPages 完成百分比
已读天数 now - startDate 阅读持续时间
剩余页数 totalPages - currentPage 还需阅读
平均速度 currentPage / readingDays 每天阅读页数
预计完成 remainingPages / averageSpeed 还需多少天

统计展示

dart 复制代码
Widget _buildStatRow(String label, String value) {
  return Padding(
    padding: const EdgeInsets.symmetric(vertical: 4),
    child: Row(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      children: [
        Text(label, style: TextStyle(color: Colors.grey.shade600)),
        Text(value, style: TextStyle(fontWeight: FontWeight.bold)),
      ],
    ),
  );
}

// 使用
_buildStatRow('已读天数', '${_book.readingDays} 天'),
_buildStatRow('剩余页数', '${_book.remainingPages} 页'),
_buildStatRow('平均速度', '${_book.averagePagesPerDay.toStringAsFixed(1)} 页/天'),
_buildStatRow('预计完成', '${estimatedDays} 天后'),

笔记功能

多行文本输入

dart 复制代码
TextField(
  controller: _notesController,
  maxLines: 5,
  decoration: const InputDecoration(
    hintText: '记录你的阅读感受...',
    border: OutlineInputBorder(),
  ),
  onChanged: (_) => _updateNotes(),
)

实时保存

dart 复制代码
void _updateNotes() {
  setState(() {
    _book.notes = _notesController.text;
  });
  widget.onUpdate(_book);
}

数据流转

存储 详情页 列表页 用户 存储 详情页 列表页 用户 添加书籍 保存数据 点击书籍 打开详情 更新进度 回调更新 保存数据 删除书籍 回调删除 保存数据 刷新列表

空状态处理

dart 复制代码
if (books.isEmpty) {
  return Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Icon(
          Icons.menu_book,
          size: 64,
          color: Colors.grey.shade300,
        ),
        const SizedBox(height: 16),
        Text(
          '还没有在读的书籍',
          style: TextStyle(color: Colors.grey.shade400, fontSize: 16),
        ),
        Text(
          '点击右下角添加书籍',
          style: TextStyle(color: Colors.grey.shade400, fontSize: 14),
        ),
      ],
    ),
  );
}

扩展思路

阅读追踪扩展
数据分析
阅读时长统计
月度阅读报告
年度阅读总结
阅读趋势图
社交功能
书评分享
好友推荐
阅读小组
读书打卡
内容增强
书籍封面
ISBN扫描
豆瓣API
在线书库
提醒功能
阅读提醒
目标设定
每日打卡
完成庆祝

阅读目标系统(扩展)

目标设定

dart 复制代码
class ReadingGoal {
  int booksPerYear;
  int pagesPerDay;
  int minutesPerDay;
  
  bool isAchieved(List<Book> books) {
    final thisYear = books.where((b) => 
      b.finishDate?.year == DateTime.now().year
    ).length;
    return thisYear >= booksPerYear;
  }
}

进度可视化

dart 复制代码
CircularProgressIndicator(
  value: completedBooks / goalBooks,
  backgroundColor: Colors.grey.shade200,
  valueColor: AlwaysStoppedAnimation(Colors.green),
)

性能优化

1. 列表优化

dart 复制代码
ListView.builder(
  itemCount: books.length,
  itemBuilder: (context, index) => _buildBookCard(books[index]),
)

使用 ListView.builder 而非 ListView,实现懒加载。

2. 数据缓存

dart 复制代码
// 只在需要时保存
void _updateBook(Book book) {
  setState(() {
    final index = _books.indexWhere((b) => b.id == book.id);
    if (index != -1) {
      _books[index] = book;
    }
  });
  _saveBooks();  // 立即保存
}

3. 状态管理

dart 复制代码
// 使用回调而非全局状态
BookDetailPage(
  book: book,
  onUpdate: _updateBook,
  onDelete: _deleteBook,
)

总结

这个阅读进度追踪应用实现了完整的书籍管理功能,核心技术点包括:

  1. 数据建模 - 完善的Book模型和计算属性
  2. JSON序列化 - toJson/fromJson实现数据持久化
  3. TabBar导航 - 三标签分类管理
  4. 统计分析 - 多维度阅读数据统计
  5. 状态管理 - 回调模式实现页面间通信

通过这个项目,可以学习到实用应用开发的完整流程,从数据建模到UI设计,从统计分析到用户体验,是Flutter开发的优秀实践案例。

阅读是一种习惯,记录是一种坚持。希望这个应用能帮助你养成良好的阅读习惯!📚
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.csdn.net

相关推荐
世人万千丶2 小时前
鸿蒙跨端框架 Flutter 学习 Day 4:程序生存法则——异常捕获与异步错误处理的熔断艺术
学习·flutter·华为·harmonyos·鸿蒙
向前V2 小时前
Flutter for OpenHarmony数独游戏App实战:底部导航栏
javascript·flutter·游戏
小白阿龙2 小时前
鸿蒙+Flutter 跨平台开发——简易猜数字竞猜游戏实现
flutter·游戏·harmonyos
鱼子酱酱酱3 小时前
#Flutter中使用Shelf做服务器框架
flutter·shelf
IT陈图图3 小时前
基于 Flutter × OpenHarmony 图书馆管理系统之构建借阅记录模块
flutter·正则表达式·openharmony
时光慢煮3 小时前
基于 Flutter × OpenHarmony 图书馆管理系统之构建书籍列表
flutter·华为·开源·openharmony
不爱吃糖的程序媛4 小时前
在 腾讯Kuikly 跨平台框架中实现设备信息检测(支持鸿蒙)
华为·harmonyos
LawrenceLan5 小时前
Flutter 零基础入门(二十一):Container、Padding、Margin 与装饰
开发语言·前端·flutter·dart
IT陈图图5 小时前
跨端智慧图书馆:Flutter × OpenHarmony 下的读者管理模块构建实践
flutter·华为·鸿蒙·openharmony