You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 08:41:39