Xamarin.Forms投篮计时器精度异常及暂停续计时问题咨询
投篮计时器精准实现方案
嘿,刚接触Xamarin就能动手做投篮计时器,很棒!你的现有代码遇到的计时精度不准、暂停重启跳秒问题,主要是因为用了System.Timers.Timer的固定间隔减数值的方式——这种方式很容易因为计时器本身的误差累积导致不准,而且暂停后没记录实际流逝的时间,重启自然会跳秒。
咱们换个思路,用**Stopwatch+DispatcherTimer**的组合来实现,这能保证时间计算的精准性,同时完美支持暂停后从当前位置继续计时。
问题根源分析
System.Timers.Timer的间隔不是绝对精准的,每次Elapsed事件触发时间有偏差,多次累积就会导致计时不准- 暂停后重启时,没有记录到暂停时已经流逝的实际时间,而是直接继续减固定值,必然会跳秒
- 最后一秒的0.01秒递减逻辑依赖10ms的计时器间隔,但计时器触发不保证绝对准时,误差会被放大
优化后的完整代码
public partial class MainPage : ContentPage { private DispatcherTimer _timer; private Stopwatch _stopwatch; private double _totalDuration = 30; // 总计时时长30秒 private double _remainingTime; public MainPage() { InitializeComponent(); // 初始化DispatcherTimer,10ms间隔保证最后一秒的小数显示流畅 _timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(10) }; _timer.Tick += OnTimerTick; _stopwatch = new Stopwatch(); _remainingTime = _totalDuration; UpdateTimerDisplay(); // 初始显示30 } private void BtnStart_Clicked(object sender, EventArgs e) { if (!_timer.IsEnabled) { _stopwatch.Start(); _timer.Start(); } } private void BtnPause_Clicked(object sender, EventArgs e) { _timer.Stop(); _stopwatch.Stop(); // 记录暂停时的剩余时间,重置秒表以便下次启动重新计时 _remainingTime -= _stopwatch.Elapsed.TotalSeconds; _stopwatch.Reset(); } private void OnTimerTick(object sender, EventArgs e) { // 用秒表的实际流逝时间计算剩余时长,完全避免累积误差 double currentRemaining = _remainingTime - _stopwatch.Elapsed.TotalSeconds; // 处理计时结束的情况 if (currentRemaining <= 0) { currentRemaining = 0; _timer.Stop(); _stopwatch.Stop(); } UpdateTimerDisplay(currentRemaining); } private void UpdateTimerDisplay(double time = 30) { // 根据剩余时间切换显示格式:大于1秒显示整数,最后1秒显示两位小数 lblTimer.Text = time > 1 ? time.ToString("0") : time.ToString("0.00"); } }
方案优势说明
- 精准无误差:
Stopwatch基于系统高分辨率计时器,能精确记录实际流逝的时间,剩余时间计算完全依赖真实流逝时长,不会有累积误差 - 暂停续接流畅:暂停时会计算并保存当前剩余时间,重启时秒表从零开始累加,再用剩余时间减去累加值,完美实现从暂停点继续
- UI线程友好:
DispatcherTimer直接在UI线程运行,不需要手动调用Device.BeginInvokeOnMainThread更新UI,避免线程问题 - 显示逻辑清晰:通过单独的
UpdateTimerDisplay方法处理显示格式,大于1秒显示整数,最后1秒自动切换为两位小数,符合需求
小细节提示
- 如果希望最后一秒的小数显示更平滑,可以把
DispatcherTimer的间隔调小到5ms,但10ms已经足够流畅且不会过多占用资源 - 计时结束时可以添加额外逻辑,比如播放提示音或者改变UI样式,增强用户体验
内容的提问来源于stack exchange,提问作者Sebastiaan
相关产品推荐
相关产品推荐

