Как сложить изображения в представлении коллекции так, чтобы они помещались на экране в Xamarin Forms?

avatar
user1447679
1 июля 2021 в 18:04
183
1
1

Цель: у меня есть 10 изображений, 4 из которых особенные. Я хочу, чтобы 4 специальных изображения соответствовали всему экрану. Я думаю, что на самом деле сделал это, но он не учитывает вкладки в нижней части приложения из AppShell.xaml. Таким образом, кажется, что оно подходит правильно, но четвертое изображение частично находится за вкладками и заставляет пользователя прокручивать.

У меня было два представления коллекции на странице, и это заставляло второе прокручиваться внутри собственного фрейма, что было странно. Поэтому, чтобы решить эту проблему, я поместил 4 специальных изображения в шаблон заголовка представления коллекции.

Вот что у меня есть, а затем то, что я хочу:

<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, другой — остальные.

Источник
Jason
1 июля 2021 в 18:14
0

во-первых, будет полезно изображение, иллюстрирующее конечную цель и текущую проблему. Во-вторых, CV - это прокручиваемые контейнеры, "прокрутка в своем собственном фрейме" - это нормальное поведение. Вы не должны вкладывать их в другой вид прокрутки. В-третьих, требования, которые у вас есть, лучше подходят для карусели.

Shaw
1 июля 2021 в 20:28
1

Карусель можно сделать. Сделайте свои первые четыре изображения другим шаблоном, который может лучше соответствовать списку. И если вы рассмотрели горизонтальную ориентацию, может быть легко поместиться на экране.

user1447679
1 июля 2021 в 20:43
0

@ Шоу, я не совсем уверен, что понимаю, новичок. Я добавил пример иллюстрации к вопросу о том, чего я пытаюсь достичь.

user1447679
1 июля 2021 в 20:48
0

Причина 4 в том, что это изображения с действиями... как если бы они были кнопками/ссылками.

Shaw
1 июля 2021 в 21:34
2

Оперативно - не проблема. Я хотел сказать data-templates/selector (я не указал точное слово в своем последнем комментарии), поэтому шаблон A имеет 4 изображения в одной ячейке, а шаблон 2 получает только одно изображение, с селектором, а данные модели также нуждаются в небольшом украшении.

Cherry Bu - MSFT
2 июля 2021 в 01:39
1

@user1447679 user1447679 Согласно вашему описанию, я не уверен, в чем ваша проблема. Как сказал Джейсон, вы можете попробовать взглянуть Xamarin.Forms CarouselView Data, и если вы хотите щелкнуть изображение как кнопку, вы можете добавить распознаватель жестов касания в изображение.

user1447679
2 июля 2021 в 06:26
0

Я учусь :) Основная проблема, с которой я столкнулся, заключается не в самой карусели, а в том, чтобы первые 4 элемента находились на одной странице и рассматривались как один элемент карусели. Спасибо. Посмотрю на эту ссылку @CherryBu-MSFT

Cherry Bu - MSFT
5 июля 2021 в 07:15
0

@ user1447679 Жду ваших отзывов.

user1447679
5 июля 2021 в 14:26
0

Спасибо @CherryBu-MSFT. Я не позволю ему сидеть. Мне пришлось развернуться. Я сделаю это еще раз в ближайшее время. Конечно, если кто-нибудь может предоставить пример кода с каруселью, это было бы здорово. В противном случае я думаю, что смогу понять это и опубликую, когда закончу.

user1447679
6 июля 2021 в 18:47
0

Спасибо всем, пожалуйста, посмотрите мой ответ и разъясните, есть ли лучший способ справиться с этим.

Ответы (1)

avatar
user1447679
6 июля 2021 в 18:47
0

Некоторые ответы смотрели на меня из примеров, и я даже не осознавал этого. Я не могу полностью взять на себя ответственность за ответ, но я добавлю соответствующие фрагменты, чтобы дать кому-то еще преимущество, с, надеюсь, более точным пониманием того, что нужно.

Источник: 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<171283677. >. Так что да, бессмысленный экземпляр, кроме его дочерних спотлетов.

Затем я переместил в свой основной список оставшиеся элементы, где IsSpotlight имеет значение false. Теперь может быть гораздо лучший способ справиться с этим, но я новичок в Xamarin, это то, что сработало для меня (подсказка: скажите мне лучший способ).

Итак, на данный момент у меня есть список спотлетов, первый из которых имеет вложенные спотлеты, а свойство IsSpotlight имеет значение true.

Теперь в моем файле XAML у меня есть карусельное представление:

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

Это ссылка на статический ресурс, который является локальным для того же файла и дочерним элементом оболочки <ContentPage />

<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, который я создал, который выполняет простую тройную операцию, чтобы вернуть используемый шаблон.

Обратите внимание, что в моем шаблоне с несколькими элементами есть вложенное представление коллекции. Остальное, только одно изображение.