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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 19:12:42