如何在Xamarin加载指示器中显示进度百分比并重置进度
Xamarin加载指示器进度不重置问题解决
问题描述
在Xamarin共享项目中实现了带百分比显示的加载指示器,但存在进度不重置的问题:返回主页面后再次进入目标页面,加载进度不会从1%开始,而是从上一次停止的位置继续累加。
问题原因
- 加载指示器中的
progress字段是类级私有变量,未在每次加载前重置为0; - 定时器在控件构造时启动后持续运行(
TimerElapsed始终返回true),即使控件不可见,进度仍在后台累加; - 控件实例可能被复用或持久化,导致上次的进度值被保留。
解决方案
1. 重构LoadingIndicator控件
修改控件代码,添加进度重置、定时器启停方法,避免定时器无效运行:
public partial class LoadingIndicator : ContentView { private int progress = 0; private bool _timerRunning = false; public LoadingIndicator() { InitializeComponent(); IsVisible = false; } /// <summary> /// 重置进度为0 /// </summary> public void ResetProgress() { progress = 0; Txt.Text = "Progress: 0%"; } /// <summary> /// 启动加载定时器 /// </summary> public void StartLoading() { if (!_timerRunning) { _timerRunning = true; Device.StartTimer(TimeSpan.FromMilliseconds(300.0), TimerElapsed); } IsVisible = true; } /// <summary> /// 停止加载定时器 /// </summary> public void StopLoading() { _timerRunning = false; IsVisible = false; } bool TimerElapsed() { Device.BeginInvokeOnMainThread(() => { if (progress < 100) { progress++; Txt.Text = $"Progress: {progress}%"; } }); // 根据状态决定是否继续定时器 return _timerRunning; } }
2. 修改调用逻辑
在触发加载的代码中,每次启动加载前重置进度并启动定时器,加载完成后停止定时器:
private async void ProductTypeButton_Clicked(object sender, EventArgs e) { _Model.IsProcessing = true; // 假设你的LoadingIndicator实例名为loadingIndicator loadingIndicator.ResetProgress(); loadingIndicator.StartLoading(); await _Model.GetProductStatus(); await Task.Delay(300); try { await Navigation.PushAsync(new ProductTypePage(_Model)); } finally { _Model.IsProcessing = false; loadingIndicator.StopLoading(); } }
3. 可选:MVVM模式优化(推荐)
如果项目采用MVVM架构,可以通过消息中心实现控件与ViewModel的解耦:
ViewModel中添加消息通知
private bool _isProcessing; public bool IsProcessing { get => _isProcessing; set { _isProcessing = value; OnPropertyChanged(); if (_isProcessing) { MessagingCenter.Send(this, "StartLoading"); } else { MessagingCenter.Send(this, "StopLoading"); } } }
LoadingIndicator中订阅消息
public LoadingIndicator() { InitializeComponent(); IsVisible = false; MessagingCenter.Subscribe<YourViewModelType>(this, "StartLoading", (sender) => { ResetProgress(); StartLoading(); }); MessagingCenter.Subscribe<YourViewModelType>(this, "StopLoading", (sender) => { StopLoading(); }); }
这样无需在页面代码后台直接操作控件,更符合MVVM设计原则。
内容的提问来源于stack exchange,提问作者Raj
相关产品推荐
相关产品推荐

