Xamarin Forms实现TikTok式全屏视频滚动问题求助
实现Xamarin Forms全屏垂直滚动视频(TikTok风格)
我正在用Xamarin Forms开发类似TikTok的视频滚动效果,已完成视频列表数据模型的创建,列表能正常显示但无法全屏展示。当前核心需求:在XAML中实现每次仅全屏显示一个视频,用户滚动切换上下视频时,新视频也保持全屏状态。
现有XAML代码
<?xml version="1.0" encoding="UTF-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:videoplayer="clr-namespace:Octane.Xamarin.Forms.VideoPlayer;assembly=Octane.Xamarin.Forms.VideoPlayer" x:Class="lf.MyPages.Lomy.Discover" x:Name="leafDiscoverPage"> <Grid> <CollectionView x:Name="VideosCollectionView" ItemsLayout="VerticalList" RemainingItemsThreshold="1" Scrolled="OnScrolled" RemainingItemsThresholdReached="OnRemainingItemsThresholdReached"> <CollectionView.ItemTemplate> <DataTemplate> <Grid HeightRequest="{Binding Source={x:Reference leafDiscoverPage}, Path=Height}" WidthRequest="{Binding Source={x:Reference leafDiscoverPage}, Path=Width}"> <!-- Replace 'octane:VideoPlayer' with your actual video player control namespace --> <videoplayer:VideoPlayer Source="{Binding UserVideoBlobAdress}" AutoPlay="{Binding IsPlaying}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" /> <!-- Add other UI elements as needed --> </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </Grid> </ContentPage>
现有C#代码
public partial class Discover : ContentPage { MyUser UserConnected; ObservableRangeCollection<UserVideoModel> MyListVideo; private int _videoCount = 0; public LeafDiscover () { InitializeComponent (); MyListVideo = new ObservableRangeCollection<UserVideoModel>(); // Initialize your ListVideo with initial video links UserConnected = (MyUser)App.GetProperties("UserConnected"); OnInitVideoList(); } public void UpdateVideoUrl(List<UserVideoModel> tmpuservideo) { foreach (var tmpvide in tmpuservideo) { tmpvide.UserVideoBlobAdress = "https://fo.blob.net/app/"+tmpvide.UserVideoBlobAdress; } } async void OnInitVideoList() { var MyInitVideo = await VideosManager.GetVideoAsync(UserConnected.MyId.ToString(), false, ""); UpdateVideoUrl(MyInitVideo); foreach (var tmpvide in MyInitVideo) { Console.WriteLine("mook "+ tmpvide.UserVideoBlobAdress); } MyListVideo.AddRange(MyInitVideo); VideosCollectionView.ItemsSource = MyListVideo; } private void OnRemainingItemsThresholdReached(object sender, EventArgs e) { if (_videoCount >= 20) { // Load more videos or handle the end of the list _videoCount = 0; } } private void OnScrolled(object sender, ItemsViewScrolledEventArgs e) { // Determine the visible item and update playback var centerIndex = e.CenterItemIndex; UpdateVideoPlayback(centerIndex); } private void UpdateVideoPlayback(int centerIndex) { for (int i = 0; i < MyListVideo.Count; i++) { MyListVideo[i].IsPlaying = i == centerIndex; } } protected override void OnAppearing() { base.OnAppearing(); // Optionally start playing the first video or the video in the center if (MyListVideo.Count > 0) { MyListVideo[0].PlayVideo(); // or another index if needed } } protected override void OnDisappearing() { base.OnDisappearing(); // Stop all videos foreach (var video in MyListVideo) { video.StopVideo(); } } }
解决方案
1. 调整CollectionView布局,强制全屏item
默认VerticalList布局不会强制item占满全屏,改用VerticalLinearItemsLayout并清除间距,同时让CollectionView占满父容器:
<CollectionView x:Name="VideosCollectionView" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" RemainingItemsThreshold="1" Scrolled="OnScrolled" RemainingItemsThresholdReached="OnRemainingItemsThresholdReached"> <CollectionView.ItemsLayout> <VerticalLinearItemsLayout ItemSpacing="0" /> </CollectionView.ItemsLayout> <!-- 其余代码不变 --> </CollectionView>
2. 优化视频容器与播放模式
移除Grid的固定尺寸绑定,改用布局属性自适应,同时给视频播放器设置填充模式避免黑边:
<DataTemplate> <Grid HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand"> <videoplayer:VideoPlayer Source="{Binding UserVideoBlobAdress}" AutoPlay="{Binding IsPlaying}" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Aspect="AspectFill" /> </Grid> </DataTemplate>
3. 修复滚动时的视频切换判断
原CenterItemIndex判断不准确,改用VisibleItems获取当前完全可见的视频项:
private void OnScrolled(object sender, ItemsViewScrolledEventArgs e) { var visibleItems = VideosCollectionView.VisibleItems; if (visibleItems == null || visibleItems.Count == 0) return; var currentVisibleIndex = MyListVideo.IndexOf(visibleItems[0] as UserVideoModel); UpdateVideoPlayback(currentVisibleIndex); }
4. 处理页面尺寸变化
页面旋转或尺寸改变时,刷新列表确保item尺寸适配:
public LeafDiscover() { InitializeComponent(); // 其余初始化代码 SizeChanged += OnPageSizeChanged; } private void OnPageSizeChanged(object sender, EventArgs e) { VideosCollectionView.ItemsSource = null; VideosCollectionView.ItemsSource = MyListVideo; }
额外注意
确保UserVideoModel实现INotifyPropertyChanged接口,这样IsPlaying属性变更时能实时触发UI更新播放状态。
内容的提问来源于stack exchange,提问作者hk77
相关产品推荐
相关产品推荐

