Flutter 如何添加支持API动态时长、带星级判定的线性计时器
Flutter线性计时器实现方案
核心需求梳理
- 总时长默认60秒,支持API返回结果动态调整
- 星级判定规则:
- 耗时≤20秒 → 3星
- 20秒<耗时≤40秒 → 2星
- 40秒<耗时≤60秒 → 1星
- 进度条固定在屏幕顶部,随时间动态推进
实现步骤
第一步:定义状态变量
在页面State类中添加以下变量:
import 'dart:async'; // 导入Timer依赖 // 总时长,默认60秒,API请求成功后更新 int totalDuration = 60; // 已消耗的秒数 int elapsedSeconds = 0; // 定时器实例 Timer? _timer;
第二步:实现计时器核心逻辑
// 启动计时器 void startTimer() { _timer = Timer.periodic(const Duration(seconds: 1), (timer) { if (elapsedSeconds >= totalDuration) { stopTimer(); // 计时结束自动提交逻辑可在此处添加 return; } setState(() { elapsedSeconds++; }); }); } // 停止计时器 void stopTimer() { _timer?.cancel(); } // 星级计算方法,提交答案时调用即可 int calculateStars(int usedSeconds) { if (usedSeconds <= 20) return 3; if (usedSeconds <= 40) return 2; return 1; } // 页面销毁时释放定时器,避免内存泄漏 @override void dispose() { _timer?.cancel(); super.dispose(); }
第三步:整合顶部进度条到现有代码
你提供的参考代码翻译+整合进度条后如下:
Widget build(BuildContext context) { print(MediaQuery.of(context).size.width); return Scaffold( appBar: AppBar( toolbarHeight: 23.h, backgroundColor: const Color(0xFFEF6E98), title: Column(children: <Widget>[ Align( alignment: Alignment.topCenter, child: Padding( padding: const EdgeInsets.only(right: 50), child: Text( '单词排序', style: GoogleFonts.fredokaOne( textStyle: TextStyle( fontSize: 25.0.sp, color: Colors.white, ) ), ), ), ), Align( alignment: Alignment.topCenter, child: Padding( padding: const EdgeInsets.only(right: 60, bottom: 60), child: Text( '- 当前题目: -', style: GoogleFonts.fredokaOne( textStyle: TextStyle( fontSize: 18.0.sp, color: Colors.white, ) ), ), ) ) ]), // 新增顶部线性进度条,和示例样式完全匹配 bottom: PreferredSize( preferredSize: Size.fromHeight(4.h), child: LinearProgressIndicator( value: elapsedSeconds / totalDuration, backgroundColor: Colors.white.withOpacity(0.3), valueColor: const AlwaysStoppedAnimation<Color>(Colors.white), ), ), ), body: FutureBuilder<List<QuizInfo>?>( future: futureData, builder: (context, snapshot) { if (snapshot.hasData) { List<QuizInfo>? data = snapshot.data; // API拿到数据后更新总时长、启动计时器 WidgetsBinding.instance.addPostFrameCallback((_) { setState(() { // 假设QuizInfo的duration字段存储当前题目标定时长,无数据则保留默认60秒 totalDuration = data?.first.duration ?? 60; elapsedSeconds = 0; }); startTimer(); }); return Stack(children: [ Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/background.PNG'), fit: BoxFit.cover ) ), ), // 剩余题目布局内容可在此处添加 ]); } // 接口加载中占位 return const Center(child: CircularProgressIndicator()); } ) ); }
注意事项
- 切换题目时需要先调用
stopTimer()重置计时,再重新调用startTimer()启动新题计时 - 总时长调整后进度条会自动适配比例,无需额外修改布局逻辑
- 提交答案时直接调用
calculateStars(elapsedSeconds)即可获取对应星级
内容的提问来源于stack exchange,提问作者LearnFlutter
相关产品推荐
相关产品推荐

