在 MAUI 中实现加载中(Loading)覆盖层,核心思路是用一个半透明的遮罩层包裹
ActivityIndicator,并控制其可见性。关键在于:遮罩要覆盖整个页面、不干扰底层交互(靠
InputTransparent="True")、且能灵活开关。
用 Grid 实现全屏 Loading 覆盖层
推荐在页面根容器(如
Grid)中叠加一层
Grid作为遮罩,内部放
ActivityIndicator和可选的文字提示。这样结构清晰、定位可控、不影响原布局。 外层
Grid作为页面主容器,所有原始内容放在第一行(
Row="0") 第二行(
Row="1")放遮罩层,设置
VerticalOptions="FillAndExpand"和
HorizontalOptions="Fill"确保铺满 遮罩层本身设
Background="Black"+
Opacity="0.4"实现半透明效果
ActivityIndicator设置
IsRunning="True"和
IsVisible="{Binding IsLoading}" 绑定控制显隐
绑定 Loading 状态并避免阻塞 UI
不要手动调用
await Task.Delay()模拟耗时操作时卡主线程。正确做法是: 在 ViewModel 中定义
bool IsLoading { get; set; } 并实现 INotifyPropertyChanged耗时逻辑用
Task.Run(() => { ... }) 或 await原生异步方法(如
HttpClient.GetAsync) 开始前设
IsLoading = true,结束后设
IsLoading = false,绑定会自动更新界面 若需禁用背景操作,可在遮罩层加
InputTransparent="False"(默认为 True),或额外给按钮等控件绑定
IsEnabled="{Binding !IsLoading}"
跨页面复用 Loading 层(推荐方式)
避免每个页面重复写遮罩代码。可封装成自定义控件或使用
ContentPage的
ControlTemplate: 新建
LoadingOverlay.xaml用户控件,内部含遮罩 + ActivityIndicator + 可选
Label暴露
BindableProperty如
IsVisibleProperty和
MessageProperty在页面中直接引用:
<loadingoverlay isvisible="{Binding IsLoading}" message="{Binding LoadingMessage}"></loadingoverlay>
更进一步可用 Shell 的 Shell.Current?.Navigation.PushAsync(new LoadingPage()),但覆盖层体验不如内嵌自然
适配不同平台与尺寸的小细节
ActivityIndicator在 Android/iOS/Windows 行为略有差异,注意以下几点: iOS 上默认不显示文字,如需提示语建议额外加
Label并居中对齐 Android 的旋转动画较明显,Windows 可能偏小,可通过
WidthRequest和
HeightRequest统一设为 60 遮罩层用
Grid而不用
StackLayout,避免因堆叠顺序导致
ActivityIndicator被盖住 测试时切到后台再切回,确保
IsLoading状态没被意外重置(必要时在
OnAppearing补检查)
基本上就这些。MAUI 的
ActivityIndicator本身轻量,难点在于遮罩的层级控制和状态同步。只要结构理清、绑定到位,Loading 效果既简洁又可靠。
