Xamarin.Forms:视频加载完成后隐藏ActivityIndicator的方法
解决Xamarin.Forms中视频加载完成后隐藏ActivityIndicator和标签的问题
首先,你需要利用Rox.Xamarin.Video.Portable库中VideoView控件的**MediaOpened事件**——这个事件会在视频资源完全加载完成、准备好播放时触发,正好是我们隐藏加载提示的时机。下面分两种常见场景给出解决方案:
一、代码隐藏(Code-Behind)方式
1. 修改你的XAML代码
首先给VideoView添加MediaOpened事件,同时给ActivityIndicator和Label设置x:Name,方便后台代码访问:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:PreAppStructure" xmlns:roxv="clr-namespace:Rox;assembly=Rox.Xamarin.Video.Portable" x:Class="PreAppStructure.Page3" Title="Welcome to page 3"> <!-- 用RelativeLayout让视频覆盖全屏,加载提示居中 --> <RelativeLayout> <!-- 视频播放器 --> <roxv:VideoView x:Name="videoPlayer" Source="你的视频源路径/URL" MediaOpened="VideoPlayer_MediaOpened" MediaFailed="VideoPlayer_MediaFailed" <!-- 可选:处理加载失败的情况 --> RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width}" RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height}"/> <!-- 加载提示区域 --> <StackLayout RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=-75}" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.5, Constant=-30}"> <ActivityIndicator x:Name="loadingIndicator" IsRunning="True" Color="White" IsVisible="True"/> <Label x:Name="loadingLabel" Text="视频加载中..." TextColor="White" HorizontalTextAlignment="Center"/> </StackLayout> </RelativeLayout> </ContentPage>
2. 在后台代码中实现事件处理
打开Page3.xaml.cs,添加两个事件处理方法:
using Xamarin.Forms; namespace PreAppStructure { public partial class Page3 : ContentPage { public Page3() { InitializeComponent(); } // 视频加载完成时触发 private void VideoPlayer_MediaOpened(object sender, System.EventArgs e) { // 停止指示器动画并隐藏控件 loadingIndicator.IsRunning = false; loadingIndicator.IsVisible = false; loadingLabel.IsVisible = false; } // 可选:视频加载失败时触发 private void VideoPlayer_MediaFailed(object sender, Rox.MediaFailedEventArgs e) { loadingIndicator.IsRunning = false; loadingIndicator.IsVisible = false; // 可以修改标签提示错误,或者直接隐藏 loadingLabel.Text = "视频加载失败,请重试"; // loadingLabel.IsVisible = false; } } }
二、MVVM模式(推荐用于大型项目)
如果你的项目采用MVVM架构,可以通过EventToCommandBehavior将控件事件绑定到ViewModel的命令,避免直接操作UI控件:
1. 实现EventToCommandBehavior
先创建一个通用的行为类:
using Xamarin.Forms; using System.Windows.Input; namespace PreAppStructure { public class EventToCommandBehavior : Behavior<View> { public static readonly BindableProperty EventNameProperty = BindableProperty.Create(nameof(EventName), typeof(string), typeof(EventToCommandBehavior), null); public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(EventToCommandBehavior), null); public string EventName { get => (string)GetValue(EventNameProperty); set => SetValue(EventNameProperty, value); } public ICommand Command { get => (ICommand)GetValue(CommandProperty); set => SetValue(CommandProperty, value); } protected override void OnAttachedTo(View bindable) { base.OnAttachedTo(bindable); var eventInfo = bindable.GetType().GetEvent(EventName); eventInfo?.AddEventHandler(bindable, new System.EventHandler(OnEventFired)); } protected override void OnDetachingFrom(View bindable) { var eventInfo = bindable.GetType().GetEvent(EventName); eventInfo?.RemoveEventHandler(bindable, new System.EventHandler(OnEventFired)); base.OnDetachingFrom(bindable); } private void OnEventFired(object sender, System.EventArgs e) { Command?.Execute(e); } } }
2. 修改XAML绑定
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:PreAppStructure" xmlns:roxv="clr-namespace:Rox;assembly=Rox.Xamarin.Video.Portable" x:Class="PreAppStructure.Page3" Title="Welcome to page 3"> <ContentPage.BindingContext> <local:Page3ViewModel/> </ContentPage.BindingContext> <RelativeLayout> <roxv:VideoView Source="{Binding VideoSource}"> <roxv:VideoView.Behaviors> <local:EventToCommandBehavior EventName="MediaOpened" Command="{Binding VideoLoadedCommand}"/> <local:EventToCommandBehavior EventName="MediaFailed" Command="{Binding VideoLoadFailedCommand}"/> </roxv:VideoView.Behaviors> </roxv:VideoView> <StackLayout RelativeLayout.XConstraint="{ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.5, Constant=-75}" RelativeLayout.YConstraint="{ConstraintExpression Type=RelativeToParent, Property=Height, Factor=0.5, Constant=-30}"> <ActivityIndicator IsRunning="{Binding IsVideoLoading}" IsVisible="{Binding IsVideoLoading}" Color="White"/> <Label Text="{Binding LoadingText}" TextColor="White" HorizontalTextAlignment="Center" IsVisible="{Binding IsVideoLoading}"/> </StackLayout> </RelativeLayout> </ContentPage>
3. 编写ViewModel
using Xamarin.Forms; using System.Windows.Input; namespace PreAppStructure { public class Page3ViewModel : INotifyPropertyChanged { private bool _isVideoLoading = true; private string _loadingText = "视频加载中..."; public bool IsVideoLoading { get => _isVideoLoading; set { _isVideoLoading = value; OnPropertyChanged(nameof(IsVideoLoading)); } } public string LoadingText { get => _loadingText; set { _loadingText = value; OnPropertyChanged(nameof(LoadingText)); } } public string VideoSource { get; set; } = "你的视频源路径/URL"; public ICommand VideoLoadedCommand { get; } public ICommand VideoLoadFailedCommand { get; } public Page3ViewModel() { VideoLoadedCommand = new Command(() => IsVideoLoading = false); VideoLoadFailedCommand = new Command(() => { IsVideoLoading = false; LoadingText = "视频加载失败,请重试"; }); } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } }
这样无论视频加载成功还是失败,都能正确控制加载提示的显示状态啦!
内容的提问来源于stack exchange,提问作者Tom F
相关产品推荐
相关产品推荐

