集合视图。屏幕上的 const 图像数量。 Xamarin 表单

Posted

技术标签:

【中文标题】集合视图。屏幕上的 const 图像数量。 Xamarin 表单【英文标题】:CollectionView. const number of images on screen. Xamarin Forms 【发布时间】:2022-01-21 23:22:21 【问题描述】:

我有图像的集合视图。我实现了 const number(5) 个图像,以使用相对布局进行查看。在我的手机上看起来不错。 但是在其他屏幕尺寸不同的手机上,它的图像比我需要的要多。 如何在所有屏幕上制作 const 数量的图像?

这是我的 XAML:

<Grid VerticalOptions="Center" HorizontalOptions="FillAndExpand">
        <Grid.RowDefinitions>
            <RowDefinition Height="44"/>
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="44"/>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="44"/>
        </Grid.ColumnDefinitions>
        <BoxView Color="Red" Grid.Row="0" Grid.Column="0"/>
        <BoxView Color="Red" Grid.Row="0" Grid.Column="2"/>
        <CollectionView Grid.Row="0" Grid.Column="1" x:Name="clv" ItemsSource="Binding ImagesArray" HorizontalOptions="FillAndExpand" VerticalOptions="Center">
            <CollectionView.ItemsLayout>
                <LinearItemsLayout Orientation="Horizontal" SnapPointsAlignment="Start" SnapPointsType="Mandatory" ItemSpacing="0"/>
            </CollectionView.ItemsLayout>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <RelativeLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
                        <Image Source="Binding ImageName"
                           RelativeLayout.HeightConstraint="ConstraintExpression Type=RelativeToParent, Property=Height, Factor=1, Constant=0"
                       RelativeLayout.XConstraint="ConstraintExpression Type=RelativeToParent, Property=Width, Factor=0.035, Constant=0"/>
                    </RelativeLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>

【问题讨论】:

使用 xamarin.forms 已经有一段时间了,但如果我没记错的话,您应该有一个 onscrolled 事件,您可以将其绑定到一个命令,该命令将您的 ImagesArray 值更改为在其中包含正确的值.它不干净,但应该可以解决问题 此链接(docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/…) 可能对您有所帮助。 当集合超过5个时,是否应该滚动? @ToolmakerSteve,是的,应该 @WenxuLi-MSFT 抱歉,我之前看过这个页面,但没有找到如何做到这一点的信息。你能给我更多的信息吗? 【参考方案1】:

案例 A:无滚动 - 所有项目都适合。

使用VerticalGrid

<Grid ColumnSpacing="0" VerticalOptions="Center"
      RowDefinitions="44" ColumnDefinitions="44,*,44">
    <BoxView Color="Red" Grid.Row="0" Grid.Column="0"/>
    <BoxView Color="Red" Grid.Row="0" Grid.Column="2"/>
    <CollectionView Grid.Row="0" Grid.Column="1" x:Name="clv" ItemsSource="Binding ImagesArray" 
                    ItemsLayout="VerticalGrid, 5" >
        <CollectionView.ItemTemplate>
            <DataTemplate>
                <Grid ColumnDefinitions="*,Auto,*">
                    <BoxView Grid.Column="1" WidthRequest="40" Color="Blue" VerticalOptions="Center"/>
                </Grid>
            </DataTemplate>
        </CollectionView.ItemTemplate>
    </CollectionView>
</Grid>

"VerticalGrid, 5" 表示每行有 5 个项目。 这些项目将在 CollectionView 的宽度上均匀分布。

注意:ColumnSpacing="0" 在外部网格中,以最大化中间列(集合视图)的可用空间。

在 ItemTemplate 中,我使用了一个 3 列的 Grid 来使 BoxView 居中。这是必需的,因为 BoxView 想要填充网格单元的整个宽度。其他元素可能不需要这个 - 而是尝试 Horizo​​ntalOptions=Center 或 Horizo​​ntalTextAlignment=Center(用于标签)。


案例 B:水平滚动 - 已知项目和边框宽度。

EvenlySpaceItemsScrolling.xaml:

<ContentPage.Content>
    <Grid ColumnSpacing="0" VerticalOptions="Center"
          RowDefinitions="44" ColumnDefinitions="44,*,44">
        <BoxView Color="Red" Grid.Row="0" Grid.Column="0"/>
        <BoxView Color="Red" Grid.Row="0" Grid.Column="2"/>
        <CollectionView Grid.Row="0" Grid.Column="1" x:Name="clv" ItemsSource="Binding ImagesArray">
            <CollectionView.ItemsLayout>
                <LinearItemsLayout x:Name="MyItemsLayout" Orientation="Horizontal" ItemSpacing="10"/>
            </CollectionView.ItemsLayout>
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <StackLayout>
                        <BoxView WidthRequest="30" HeightRequest="30" Color="Blue" VerticalOptions="Center"/>
                    </StackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>
</ContentPage.Content>

EvenlySpaceItemsScrolling.xaml.cs:

using System;
using System.Collections.ObjectModel;

using Xamarin.Essentials;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace TestBugs

    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class EvenlySpaceItemsScrolling : ContentPage
    
        const int NItemsToShow = 5;
        const int ItemWidth = 30;

        public EvenlySpaceItemsScrolling()
        
            InitializeComponent();

            BindingContext = this;
        

        protected override void OnAppearing()
        
            base.OnAppearing();

            // If the amount of space to left and right of scrolling area is known,
            // we can handle it before the page is laid out.
            // See xaml: the width of left column is 44, right column is 44.
            const int SubtractThisWidth = 44 + 44;
            int collectionWidth = (int)ScreenLogicalWidth() - SubtractThisWidth;
            SetSpacingAndMargin(NItemsToShow, ItemWidth, collectionWidth);
        


        private void SetSpacingAndMargin(int nItemsToShow, int itemWidth, int collectionWidth)
        
            int widthPerItem = collectionWidth / nItemsToShow;
            int spacing = Math.Max(0, widthPerItem - itemWidth);
            int leftMargin = spacing / 2;

            this.MyItemsLayout.ItemSpacing = spacing;
            this.clv.Margin = new Thickness(leftMargin, 0, 0, 0);

            // --- Manually test values that work well at a specific screen width. ---
            //this.MyItemsLayout.ItemSpacing = 30;
            //this.clv.Margin = new Thickness(15, 0, 0, 0);
        

        public static double ScreenLogicalWidth()
        
            return DeviceDisplay.MainDisplayInfo.Width / DeviceDisplay.MainDisplayInfo.Density;
        

        // For demo, this is only used to get a count of items.
        // Replace with your actual source.
        public ObservableCollection<Model> ImagesArray  get; set;  = new ObservableCollection<Model> 
            new Model(),
            new Model(),
            new Model(),
            new Model(),
            new Model(),
        ;
    


案例 C:水平滚动 - 测量集合宽度。

EvenlySpaceItemsScrolling.xaml - 与案例 B 相同。

EvenlySpaceItemsScrolling.xaml.cs - 参见案例 B,但删除 OnAppearing 中的代码,并添加:

    protected override void LayoutChildren(double x, double y, double width, double height)
    
        base.LayoutChildren(x, y, width, height);

        // Dynamically calculate based on collection width.
        int collectionWidth = (int)this.clv.Width;
        SetSpacingAndMargin(NItemsToShow, ItemWidth, collectionWidth);
    

【讨论】:

谢谢你的回答,但我真的需要水平方向的布局,因为我的收藏中的项目数量不是静态的,它可能从 6 到 12 不等。 添加了计算间距的代码。 抱歉回复太长了。我测试了你的例子。它有一个不正确的时刻。如果我将屏幕方向更改为“横向”一切正常,项目间距计算正确。但是如果我改变方向,项目间距变为零。你能帮忙吗?我使用案例“C”,因为在我的项目中我不能使用 Xamarin.Essentials 来获取屏幕尺寸

以上是关于集合视图。屏幕上的 const 图像数量。 Xamarin 表单的主要内容,如果未能解决你的问题,请参考以下文章

如何在没有动画的情况下从集合视图中删除项目?

Xcode 启动屏幕上的图像视图出现片刻然后消失

我想在滚动时在列表视图中添加 500 张图像,并删除当前不在屏幕上的项目

如何使用 UICollectionViewCompositionalLayout 创建像图像一样的集合视图

集合视图平铺

在集合视图单元格中自行调整图像大小