【问题标题】:How can I stack images in a collection view so that they fit within the screen in Xamarin Forms?如何在集合视图中堆叠图像,以便它们适合 Xamarin Forms 的屏幕?
【发布时间】:2021-08-14 05:10:21
【问题描述】:

目标:我有 10 张图片,其中 4 张是特殊的。我希望 4 个特殊图像适合屏幕的整个视图。我想我实际上已经这样做了,但它没有考虑到 AppShell.xaml 中应用程序底部的选项卡。所以它看起来很合适,但第四张图片部分位于标签后面并迫使用户滚动。

我在页面上有两个集合视图,它导致第二个在它自己的框架内滚动,这很奇怪。所以为了解决这个问题,我把 4 个特殊的图片放在了 collection view 的 header 模板中。

这是我所拥有的,然后是我想要它做的:

<RefreshView x:DataType="local:SpotlightViewModel" Command="{Binding LoadItemsCommand}" IsRefreshing="{Binding IsBusy, Mode=TwoWay}" Margin="0, 0, 0, 0">
        
  <ScrollView InputTransparent="True" >
    <Grid >
      <CollectionView x:Name="SpotletsListView"
                              ItemsSource="{Binding Spotlets}"
                              EmptyView=""
                              SelectionMode="None">
        <CollectionView.ItemsLayout>
          <LinearItemsLayout SnapPointsAlignment="Start" SnapPointsType="Mandatory" Orientation="Vertical"></LinearItemsLayout>
        </CollectionView.ItemsLayout>
        <CollectionView.Header>
          <CollectionView ItemsSource="{Binding SpotlightSpotlets}">
            <CollectionView.ItemTemplate>
              <DataTemplate>
                <StackLayout Padding="0, .1" x:DataType="model:Spotlet" HorizontalOptions="Center" VerticalOptions="FillAndExpand">
                  <Image Aspect="AspectFit" HorizontalOptions="Center" Source="{Binding Url, Converter={StaticResource ImageSourceConverter}}" ></Image>
                </StackLayout>
              </DataTemplate>
            </CollectionView.ItemTemplate>
         </CollectionView>
      </CollectionView.Header>
      <CollectionView.ItemTemplate>
        <DataTemplate>
          <StackLayout Padding="0, .1" x:DataType="model:Spotlet" HorizontalOptions="Center">
            <Image Aspect="AspectFit" HorizontalOptions="Center" Source="{Binding Url, Converter={StaticResource ImageSourceConverter}}" ></Image>
          </StackLayout>
        </DataTemplate>
      </CollectionView.ItemTemplate>
    </CollectionView>
  </Grid>
</ScrollView>
</RefreshView>

我想要的很简单。对于像我这样的 Xamarin 新手来说,实现它并不是那么简单。

  1. 前四张图片填满屏幕,但占底部的标签
  2. 所有后续图像都填满屏幕
  3. 滚动时,将图像捕捉到位,这样就不会同时看到两个图像
  4. 当我到达底部时,允许继续滚动返回顶部

也许我需要在其中一部分使用轮播,我尝试过,但也遇到了一些奇怪的行为。有人可以给我一个可能有帮助的样板吗?

第 1 页:

[ -- this is an image -- ]
[ -- this is an image -- ]
[ -- this is an image -- ]
[ -- this is an image -- ]

第 2 页:

[ -- one image, fills -- ]

第 3 页:

[ -- one image, fills --]

当我到达底部时,我希望它再次无限滚动相同的项目。我在代码中有两个单独的集合。一个持有 4,另一个持有其余部分。

【问题讨论】:

  • 首先,一张说明最终目标和当前问题的图片会很有帮助。 2、CV 是可滚动的容器,“在自己的框架内滚动”是正常行为。您不应该将它们嵌套在另一个滚动视图中。第三,您的要求听起来更适合轮播。
  • 轮播视图可以做到。使您的前四张图像成为另一个模板可能更适合该列表。并且你考虑过水平方向,可能很容易适应屏幕。
  • @Shaw 我不太确定我是否理解,这里的新手。我为我想要完成的问题添加了一个示例说明。
  • 可操作没问题。我的意思是data-templates/selector(我没有在上一条评论中输入确切的词),所以模板A在一个单元格中有4张图片,而模板2只有一张图片,还有一个选择器和模型数据不过需要一点修饰。
  • @user1447679 根据您的描述,我不确定您的问题是什么。正如jason所说,你可以尝试看一下Xamarin.Forms CarouselView Data,如果你想点击图片作为Button,你可以在Image中添加a tap gesture recognizer

标签: xamarin xamarin.forms


【解决方案1】:

有些答案从示例中盯着我,我什至没有意识到。我不能完全相信答案,但我会添加相关的 sn-ps 以便让其他人抢先一步,希望能更准确地了解需要什么。

来源:https://github.com/xamarin/xamarin-forms-samples/tree/main/Templates/DataTemplateSelector

虽然您可以使用自己的 .xaml 文件将这些自定义模板抽象为复杂的视图,但在我的特定情况下,我只需要这个示例。

首先,我创建了一个类,负责为特定项目选择正确的模板:

public class SpotlightTemplateSelector : DataTemplateSelector
{
  public DataTemplate SingleItemTemplate { get; set; }
  public DataTemplate SpotlightItemTemplate { get; set; }

  protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
  {
    return ((Spotlet) item).IsSpotlight ? SpotlightItemTemplate : SingleItemTemplate;
  }
}

我的 SpotlightItemTemplate 是我想在轮播的单个框架内显示多个项目的地方。现在这可能不是最好的方法,但这就是我所做的。

我的模特:

public class Spotlet
{
    public string Url { get; set; }
    public bool IsSpotlight { get; set; }
    public List<Spotlet> Spotlets { get; set; }
}

这里的关键是最后一个道具Spotlets。当我获取所有数据时,我创建了一个 Spotlet 类的新实例来表示第一个轮播项目,并将具有 IsSpotlight 的每个项目推送到该项目 Spotlets 。所以是的,除了它的子 Spotlets 之外的一个无意义的实例。

然后我将 IsSpotlight 为假的剩余项目推送到我的主列表中。现在可能有更好的方法来处理这个问题,但我是 Xamarin 的新手,这对我有用(提示:告诉我更好的方法)。

所以此时我有一个 Spotlets 列表,第一个有嵌套 Spotlets,并且它的 IsSpotlight 属性设置为 true。

现在,在我的 XAML 文件中,我有了轮播视图:

<CarouselView x:Name="SpotletsCarousel"
   ItemsSource="{Binding Spotlets}"
   ItemTemplate="{StaticResource spotlightDataTemplateSelector}">
</CarouselView>

它引用了一个静态资源,该资源是同一文件的本地资源,并且是包装 &lt;ContentPage /&gt; 的子对象

<ContentPage.Resources>
  <ResourceDictionary>
    <DataTemplate x:Key="SpotletItemViewTemplate">
      <StackLayout x:DataType="model:Spotlet">
        <Image Aspect="AspectFill" Source="{Binding Url, Converter={StaticResource ImageSourceConverter}}" ></Image>
      </StackLayout>
    </DataTemplate>
    <DataTemplate x:Key="SpotletSpotlightItemViewTemplate" x:DataType="model:Spotlet">
      <CollectionView x:Name="SpotletsListView" ItemsSource="{Binding Spotlets }">
        <CollectionView.ItemTemplate>
          <DataTemplate>
            <StackLayout Padding="0, .1" x:DataType="model:Spotlet" HorizontalOptions="Center" VerticalOptions="FillAndExpand">
              <Image Aspect="AspectFit" HorizontalOptions="Center" Source="{Binding Url, Converter={StaticResource ImageSourceConverter}}" ></Image>
            </StackLayout>
          </DataTemplate>
        </CollectionView.ItemTemplate>
      </CollectionView>
    </DataTemplate>
    <local:SpotlightTemplateSelector x:Key="spotlightDataTemplateSelector" SingleItemTemplate="{StaticResource SpotletItemViewTemplate}" SpotlightItemTemplate="{StaticResource SpotletSpotlightItemViewTemplate}" />
  </ResourceDictionary>
</ContentPage.Resources>

我的轮播项目模板引用了本地资源中定义的 spotlightDataTemplateSelector(即 x:Key="spotlightDataTemplateSelector")。

这会调用我创建的SpotlightTemplateSelector 类中的方法,它执行一个简单的三元组来返回要使用的模板。

请注意,在我的多项目模板中,我有一个嵌套的集合视图。其余的,只是一张图片。

【讨论】:

    猜你喜欢
    • 2021-05-23
    • 2018-06-29
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 2016-08-09
    • 2015-11-05
    • 2016-11-14
    相关资源
    最近更新 更多