如何为Xamarin MediaElement视频播放器添加可用全屏按钮
Xamarin.Forms MediaElement 列表页全屏播放实现方案
当前基础播放实现代码如下:
xmlns:xct="http://xamarin.com/schemas/2020/toolkit" <xct:MediaElement Grid.Row="0" Aspect="AspectFill" HeightRequest="{OnIdiom Phone=170, Tablet=170, Desktop=170}" WidthRequest="{OnIdiom Phone=343, Tablet=343, Desktop=423}" Source="urllllllllllllllllllll" AutoPlay="True" Background="transparent" IsTabStop="True" ShowsPlaybackControls="True"/>
当前运行效果:
实现步骤
1. 修改XAML布局
首先将原有播放器和新增的全屏按钮放在同一个Grid容器内(Grid同单元格内容默认叠放,按钮写在播放器后方保证层级更高不被遮挡),同时给页面根布局、播放器、按钮设置命名,方便后台逻辑调用。
完整布局参考代码:
<!-- 页面根布局,用于全屏时挂载播放器 --> <Grid x:Name="RootGrid"> <ListView CachingStrategy="RecycleElement" x:Name="VideoList"> <ListView.ItemTemplate> <DataTemplate> <ViewCell> <StackLayout Padding="16"> <!-- 播放器外层容器 --> <Grid x:Name="PlayerContainer" HorizontalOptions="Center"> <xct:MediaElement x:Name="VideoPlayer" Grid.Row="0" Aspect="AspectFill" HeightRequest="{OnIdiom Phone=170, Tablet=170, Desktop=170}" WidthRequest="{OnIdiom Phone=343, Tablet=343, Desktop=423}" Source="urllllllllllllllllllll" AutoPlay="True" Background="transparent" IsTabStop="True" ShowsPlaybackControls="True"/> <!-- 全屏切换按钮,固定在播放器右上角 --> <ImageButton x:Name="FullScreenToggleBtn" Grid.Row="0" Source="fullscreen.png" HorizontalOptions="End" VerticalOptions="Start" Margin="0,10,10,0" HeightRequest="36" WidthRequest="36" CornerRadius="18" BackgroundColor="#50000000" Padding="8" Clicked="FullScreenToggleBtn_Clicked"/> </Grid> <!-- 列表项其他文本/内容区域 --> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid>
2. 编写全屏切换后台逻辑
因为播放器嵌在ListView列表项中,直接修改宽高无法突破列表项的布局限制,所以全屏时需要将播放器临时挂载到页面根布局,退出全屏时再放回原容器,同时处理屏幕方向、系统栏显示状态的切换。
首先在页面后台代码中定义状态记录字段:
private bool _isFullScreen = false; // 记录播放器非全屏状态下的参数,用于退出全屏时还原 private Grid _originalPlayerParent; private double _originalPlayerHeight; private double _originalPlayerWidth; private Aspect _originalPlayerAspect;
然后实现按钮点击事件:
private void FullScreenToggleBtn_Clicked(object sender, EventArgs e) { var btn = (ImageButton)sender; if (!_isFullScreen) { // 进入全屏 // 记录原始状态 _originalPlayerParent = (Grid)VideoPlayer.Parent; _originalPlayerHeight = VideoPlayer.HeightRequest; _originalPlayerWidth = VideoPlayer.WidthRequest; _originalPlayerAspect = VideoPlayer.Aspect; // 将播放器从列表项容器移到页面根布局 _originalPlayerParent.Children.Remove(VideoPlayer); RootGrid.Children.Add(VideoPlayer); // 设置播放器铺满屏幕 Grid.SetRowSpan(VideoPlayer, 999); var screenMetrics = DeviceDisplay.MainDisplayInfo; VideoPlayer.HeightRequest = screenMetrics.Height / screenMetrics.Density; VideoPlayer.WidthRequest = screenMetrics.Width / screenMetrics.Density; VideoPlayer.Aspect = Aspect.AspectFit; VideoPlayer.Margin = 0; // 隐藏导航栏,切换横屏 NavigationPage.SetHasNavigationBar(this, false); MessagingCenter.Send(this, "ForceLandscape"); // 切换按钮图标为退出全屏样式 btn.Source = "exit_fullscreen.png"; _isFullScreen = true; } else { // 退出全屏 // 将播放器移回原列表容器 RootGrid.Children.Remove(VideoPlayer); _originalPlayerParent.Children.Insert(0, VideoPlayer); // 还原播放器参数 Grid.SetRowSpan(VideoPlayer, 1); VideoPlayer.HeightRequest = _originalPlayerHeight; VideoPlayer.WidthRequest = _originalPlayerWidth; VideoPlayer.Aspect = _originalPlayerAspect; VideoPlayer.Margin = 0; // 还原导航栏,切换竖屏 NavigationPage.SetHasNavigationBar(this, true); MessagingCenter.Send(this, "ForcePortrait"); // 切换按钮图标为全屏样式 btn.Source = "fullscreen.png"; _isFullScreen = false; } }
3. 添加平台端屏幕方向控制
在各平台项目中注册消息监听,实现强制横竖屏切换:
Android端(MainActivity.cs)
在OnCreate方法中添加以下代码:
MessagingCenter.Subscribe<YourVideoListPage>(this, "ForceLandscape", page => { RequestedOrientation = ScreenOrientation.Landscape; Window.AddFlags(WindowManagerFlags.Fullscreen); }); MessagingCenter.Subscribe<YourVideoListPage>(this, "ForcePortrait", page => { RequestedOrientation = ScreenOrientation.Portrait; Window.ClearFlags(WindowManagerFlags.Fullscreen); });
记得将YourVideoListPage替换为你实际的列表页类名。
iOS端(AppDelegate.cs)
在FinishedLaunching方法中添加以下代码:
MessagingCenter.Subscribe<YourVideoListPage>(this, "ForceLandscape", page => { UIDevice.CurrentDevice.SetValueForKey(NSNumber.FromNInt((int)UIInterfaceOrientation.LandscapeLeft), new NSString("orientation")); UIApplication.SharedApplication.StatusBarHidden = true; }); MessagingCenter.Subscribe<YourVideoListPage>(this, "ForcePortrait", page => { UIDevice.CurrentDevice.SetValueForKey(NSNumber.FromNInt((int)UIInterfaceOrientation.Portrait), new NSString("orientation")); UIApplication.SharedApplication.StatusBarHidden = false; });
注意事项
- 代码中用到的
fullscreen.png、exit_fullscreen.png需要替换为你项目中实际存放的图标资源 - 列表的
CachingStrategy建议设置为RecycleElement避免列表滚动时播放器实例复用导致的状态异常 - 重写页面的
OnDisappearing方法,在页面离开时判断如果处于全屏状态先执行退出全屏逻辑,避免屏幕方向未还原影响其他页面 - 如果需要支持安卓返回键退出全屏,可以重写页面的
OnBackButtonPressed方法,判断全屏状态时先执行退出逻辑再响应返回
内容的提问来源于stack exchange,提问作者Gazdallah Amira
相关产品推荐
相关产品推荐

