无需XAML用户控件的Xamarin Forms快速加载Spinner方案求推荐
可行方案推荐
方案一:基于DependencyService实现原生加载指示器
这种方式直接调用各平台原生加载控件,无需在XAML中添加任何元素,性能更贴近原生,能避开第三方库的性能损耗。
1. 定义共享接口
在共享项目中创建统一接口:
public interface ILoadingIndicatorService { void ShowLoading(string message = "加载中..."); void HideLoading(); }
2. 各平台实现
Android平台
[assembly: Dependency(typeof(AndroidLoadingIndicatorService))] namespace YourApp.Droid.Services { public class AndroidLoadingIndicatorService : ILoadingIndicatorService { private ProgressDialog _progressDialog; public void ShowLoading(string message) { MainThread.BeginInvokeOnMainThread(() => { _progressDialog = new ProgressDialog(Android.App.Application.Context); _progressDialog.SetMessage(message); _progressDialog.SetCancelable(false); _progressDialog.Show(); }); } public void HideLoading() { MainThread.BeginInvokeOnMainThread(() => { _progressDialog?.Dismiss(); _progressDialog = null; }); } } }
iOS平台
[assembly: Dependency(typeof(IosLoadingIndicatorService))] namespace YourApp.iOS.Services { public class IosLoadingIndicatorService : ILoadingIndicatorService { private UIActivityIndicatorView _indicator; private UIView _overlay; public void ShowLoading(string message) { MainThread.BeginInvokeOnMainThread(() => { var window = UIApplication.SharedApplication.KeyWindow; _overlay = new UIView(window.Bounds) { BackgroundColor = UIColor.Black.ColorWithAlpha(0.5f), AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight }; _indicator = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.Large) { Center = _overlay.Center, AutoresizingMask = UIViewAutoresizing.FlexibleLeftMargin | UIViewAutoresizing.FlexibleRightMargin | UIViewAutoresizing.FlexibleTopMargin | UIViewAutoresizing.FlexibleBottomMargin }; _indicator.StartAnimating(); _overlay.AddSubview(_indicator); window.AddSubview(_overlay); }); } public void HideLoading() { MainThread.BeginInvokeOnMainThread(() => { _indicator?.StopAnimating(); _overlay?.RemoveFromSuperview(); _indicator = null; _overlay = null; }); } } }
UWP平台
[assembly: Dependency(typeof(UwpLoadingIndicatorService))] namespace YourApp.UWP.Services { public class UwpLoadingIndicatorService : ILoadingIndicatorService { private ContentDialog _loadingDialog; public void ShowLoading(string message) { MainThread.BeginInvokeOnMainThread(() => { _loadingDialog = new ContentDialog { Title = "", Content = new StackPanel { Orientation = Orientation.Horizontal, Children = { new ProgressRing { IsActive = true, Width = 24, Height = 24, Margin = new Thickness(0,0,10,0) }, new TextBlock { Text = message } } }, CloseButtonText = "", IsSecondaryButtonEnabled = false, IsPrimaryButtonEnabled = false, FullSizeDesired = false }; _loadingDialog.ShowAsync(); }); } public void HideLoading() { MainThread.BeginInvokeOnMainThread(async () => { if (_loadingDialog != null) { await _loadingDialog.HideAsync(); _loadingDialog = null; } }); } } }
3. 全局调用封装
在共享项目中封装静态类简化调用:
public static class LoadingManager { private static readonly ILoadingIndicatorService _service = DependencyService.Get<ILoadingIndicatorService>(); public static void Show(string message = "加载中...") => _service.ShowLoading(message); public static void Hide() => _service.HideLoading(); }
使用示例:
LoadingManager.Show("正在加载数据..."); await SomeAsyncTask(); LoadingManager.Hide();
方案二:纯代码动态创建Xamarin.Forms加载覆盖层
完全基于Xamarin.Forms控件通过代码动态生成,无需依赖原生实现,适配所有支持平台(包括UWP)。
封装调用类
public static class DynamicLoadingOverlay { private static ContentView _overlay; public static void Show(Page currentPage, string message = "加载中...") { MainThread.BeginInvokeOnMainThread(() => { var indicator = new ActivityIndicator { IsRunning = true, Color = Color.Accent, VerticalOptions = LayoutOptions.Center, HorizontalOptions = LayoutOptions.Center }; var messageLabel = new Label { Text = message, TextColor = Color.White, Margin = new Thickness(0, 10, 0, 0), HorizontalOptions = LayoutOptions.Center }; var stackLayout = new StackLayout { Children = { indicator, messageLabel }, BackgroundColor = Color.Black.WithAlpha(0.7), Padding = new Thickness(20), CornerRadius = 8 }; _overlay = new ContentView { Content = stackLayout, BackgroundColor = Color.Transparent, VerticalOptions = LayoutOptions.FillAndExpand, HorizontalOptions = LayoutOptions.FillAndExpand, GestureRecognizers = { new TapGestureRecognizer() } // 阻止点击穿透 }; currentPage.Content = new Grid { Children = { currentPage.Content, _overlay } }; }); } public static void Hide(Page currentPage) { MainThread.BeginInvokeOnMainThread(() => { if (_overlay != null && currentPage.Content is Grid grid) { grid.Children.Remove(_overlay); currentPage.Content = grid.Children[0]; _overlay = null; } }); } }
调用示例
// 显示加载 DynamicLoadingOverlay.Show(this, "处理中..."); // 执行异步操作 await YourAsyncOperation(); // 隐藏加载 DynamicLoadingOverlay.Hide(this);
方案三:基于Prism Popup(项目已集成Prism框架时使用)
若项目已经使用Prism框架,可利用其Popup功能纯代码创建加载指示器,天然支持UWP平台。
1. 创建纯代码PopupPage
public class LoadingPopupPage : PopupPage { public LoadingPopupPage(string message) { BackgroundColor = Color.Black.WithAlpha(0.5); var indicator = new ActivityIndicator { IsRunning = true, Color = Color.White, WidthRequest = 40, HeightRequest = 40 }; var messageLabel = new Label { Text = message, TextColor = Color.White, Margin = new Thickness(0, 10, 0, 0) }; Content = new StackLayout { HorizontalOptions = LayoutOptions.Center, VerticalOptions = LayoutOptions.Center, Children = { indicator, messageLabel }, BackgroundColor = Color.DarkGray, Padding = new Thickness(20), CornerRadius = 10 }; } }
2. 调用方式
通过Prism的IPopupNavigation服务调用:
// 构造函数注入IPopupNavigation private readonly IPopupNavigation _popupNavigation; public YourViewModel(IPopupNavigation popupNavigation) { _popupNavigation = popupNavigation; } // 显示加载 await _popupNavigation.PushAsync(new LoadingPopupPage("加载中...")); // 异步操作 await SomeTask(); // 隐藏加载 await _popupNavigation.PopAsync();
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

