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

Xamarin.Forms:如何利用MediaPlayer的isPlaying状态关闭ActivityIndicator?

利用MediaPlayer的isPlaying状态关闭加载提示的可行方案

嘿,这个需求完全可行!而且用isPlaying状态来判断视频加载完成并关闭ActivityIndicator和标签是个很合理的思路。不过因为Xamarin.Forms是跨平台框架,原生MediaPlayer的状态需要传递到Forms层才能绑定到IsBusy属性,我给你梳理两种具体实现方式:

方法一:自定义视频控件+原生渲染器(适合原生VideoView场景)

如果你的项目用的是原生Android VideoView,需要通过自定义渲染器把原生的播放状态传递到Forms层:

1. 在Forms项目中创建自定义视频控件

先定义一个带播放状态属性和事件的控件,用来接收原生层的状态:

public class CustomVideoPlayer : View
{
    // 定义可绑定的IsPlaying属性
    public static readonly BindableProperty IsPlayingProperty =
        BindableProperty.Create(nameof(IsPlaying), typeof(bool), typeof(CustomVideoPlayer), false);

    public bool IsPlaying
    {
        get => (bool)GetValue(IsPlayingProperty);
        set => SetValue(IsPlayingProperty, value);
    }

    // 定义播放开始的事件
    public event EventHandler PlaybackStarted;

    internal void TriggerPlaybackStarted()
    {
        PlaybackStarted?.Invoke(this, EventArgs.Empty);
    }
}

2. 实现Android平台的自定义渲染器

在Android项目中写渲染器,监听原生VideoView的Prepared事件(视频加载完成准备播放时触发),然后同步状态到Forms控件:

[assembly: ExportRenderer(typeof(CustomVideoPlayer), typeof(CustomVideoPlayerRenderer))]
namespace YourAppName.Droid.Renderers
{
    public class CustomVideoPlayerRenderer : ViewRenderer<CustomVideoPlayer, Android.Widget.VideoView>
    {
        protected override void OnElementChanged(ElementChangedEventArgs<CustomVideoPlayer> e)
        {
            base.OnElementChanged(e);

            if (Control == null)
            {
                var nativeVideoView = new Android.Widget.VideoView(Context);
                SetNativeControl(nativeVideoView);
            }

            if (e.NewElement != null)
            {
                // 监听视频准备完成事件
                Control.Prepared += OnVideoPrepared;
                // 这里可以设置视频源,比如Control.SetVideoURI(Uri.Parse("你的视频地址"));
            }

            if (e.OldElement != null)
            {
                // 取消事件订阅避免内存泄漏
                Control.Prepared -= OnVideoPrepared;
            }
        }

        private void OnVideoPrepared(object sender, EventArgs e)
        {
            Control.Start(); // 启动播放
            // 同步状态到Forms控件
            Element.IsPlaying = true;
            Element.TriggerPlaybackStarted();
        }
    }
}

3. 在Forms页面中绑定处理

在XAML里使用自定义控件,然后订阅事件来关闭IsBusy:

<StackLayout>
    <ActivityIndicator IsRunning="{Binding IsBusy}" IsVisible="{Binding IsBusy}" />
    <Label Text="视频加载中..." IsVisible="{Binding IsBusy}" />
    <local:CustomVideoPlayer x:Name="MyCustomPlayer" />
</StackLayout>

后台代码处理:

public VideoPage()
{
    InitializeComponent();
    // 开始加载视频时开启加载提示
    this.IsBusy = true;
    // 订阅播放开始事件
    MyCustomPlayer.PlaybackStarted += (s, e) => this.IsBusy = false;
    // 设置视频源(需要在自定义控件中扩展对应的方法)
    // MyCustomPlayer.SetVideoSource("你的视频URL");
}

方法二:使用第三方视频库(更快捷)

如果不想自己写渲染器,推荐用成熟的第三方库比如Plugin.MediaManager,它已经封装了播放状态的绑定属性和事件:

  1. 安装NuGet包Plugin.MediaManager和对应平台的包
  2. 在XAML中使用视频控件:
<media:VideoView x:Name="MediaPlayerView" />
  1. 后台监听播放状态:
public VideoPage()
{
    InitializeComponent();
    this.IsBusy = true;
    // 监听播放状态变化
    MediaManager.Current.StateChanged += (s, e) =>
    {
        if (e.State == MediaManager.Playback.State.Playing)
        {
            this.IsBusy = false;
        }
    };
    // 设置视频源
    await MediaManager.Current.Play("你的视频URL");
}

注意事项

  • 如果你需要处理视频缓冲的场景(比如加载后中途缓冲),可以额外监听原生VideoView的BufferingUpdate事件,不过你需求中的“完全加载完成”,用Prepared事件就足够了。
  • 记得在页面销毁时取消所有事件订阅,避免内存泄漏。

内容的提问来源于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.27 03:33:21