it-swarm.com.ru

Горизонтальный ListView Xamarin.Forms

Есть ли способ создать ListView с horizontal scroll вXamarin.Formsкак изображение 

ListView Horizontal

это то, что я сделал для вертикали 

var myListView = new ListView
{
    ItemTemplate = new DataTemplate(typeof(ImageCell))
};
25
Luigi Saggese

Да, технически вы можете. Установите Rotation в 270 (все VisualElements имеют свойство Rotation BindableProperty). Тем не менее, это выглядит как неоптимальное решение, так как есть пробелы сверху и снизу, и вы должны перетащить вид влево и вправо, чтобы увидеть все полностью. 

public static readonly BindableProperty RotationProperty;
public static readonly BindableProperty RotationXProperty;
public static readonly BindableProperty RotationYProperty;

Код выше взят из класса VisualElement. Код ниже - мой небольшой пример. 

                                              ∨∨∨                                                  
<ListView x:Name="MessagesListView" Rotation="270" ItemsSource="{Binding Items}" RowHeight="40">
  <ListView.ItemTemplate>
    <DataTemplate>
      <ViewCell>
        <ViewCell.View>
          <StackLayout>
            <!--mylayouthere-->
          </StackLayout>
        </ViewCell.View>
      </ViewCell>
    </DataTemplate>
  </ListView.ItemTemplate>
</ListView>
11
Millie Smith

Как и все остальные говорили, нет - нет ни одного доступного из коробки в Xamarin.Forms .

Однако - это не мешает никому писать собственный пользовательский рендер для достижения этого типа контроля.

Как уже упоминалось Stephane Delcroix, вы можете создать ScrollView , а затем StackLayout как дочерний элемент для создания того же эффекта.

Затем вам нужно будет реализовать:

*) связываемое свойство для принятия (IEnumerable) ItemsSource свойства, которое необходимо создать. 

*) связываемое свойство, чтобы принять (DataTemplate) ItemTemplate свойство, которое необходимо создать.

*) binding код для создания экземпляров ItemTemplate , берущий конкретный элемент источника данных и отображающий его в StackLayout . Вы должны рассмотреть элементы удалены и т.д.

*) прикреплять обработчики событий/нажимать жесты для выбора элемента. 

*) реализация выбранного состояния/деактивация других выбранных элементов.

... и так далее, чтобы получить полную реализацию.

Проблема всего вышеперечисленного заключается в том, что он подходит для относительно небольших списков предметов.

Однако, если вы ищете длинный список записей, то выше будет немного нежелательно, так как вы создаете все Views upfront. 

Даже если вы отложили загрузку из них, у вас все еще есть memory footprint из всех Views , которые следует учитывать.

Затем это приводит к другой возможной реализации, которая имеет дело с виртуализированными элементами , что является совершенно другой историей для рассмотрения.

10
Pete

Как указывалось выше, стандартного способа сделать это не существует, однако есть способ обойти его, используя стандартные подходы ListView и @MillieSmiths.

Решение нуждается в нескольких слоях вложенных макетов. Начиная с ListView мы будем поворачивать эти 270 градусов, однако это также поворачивает содержимое нашего элемента, поэтому нам нужно повернуть его обратно на 90 градусов.

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

Наконец в коде позади мы должны сделать отсечение макета

Вот полное решение:

<AbsoluteLayout x:Name="MessagesLayoutFrame" Padding="0" HorizontalOptions="FillAndExpand">
  <ContentView x:Name="MessagesLayoutFrameInner"  Padding="0"  HorizontalOptions="FillAndExpand">
    <ListView x:Name="MessagesListView"
              ItemsSource="{Binding Images}"
              RowHeight="240"
              VerticalOptions="Start"
              HeightRequest="240"
              WidthRequest="240"
              SeparatorVisibility="None"
              Rotation="270"
              HorizontalOptions="Center">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ContentView Rotation="90" Padding="12">
              <Image Source="{Binding Source}" Aspect="AspectFill" />
            </ContentView>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </ContentView>
</AbsoluteLayout>

Для кода, который нам нужен, нам просто нужно проверить, настроили ли мы что-то раньше, если есть, отпустить. По сути, мы выясняем, какова ширина страницы (NameGrid это просто контейнер полной ширины где-то еще), затем перемещаем прямой контейнер ListView на половину пустого пространства и обрезаем его на другую половину снизу)

    bool hasAppearedOnce = false;
    protected override void OnAppearing() {
        base.OnAppearing();

        if (!hasAppearedOnce) {

            hasAppearedOnce = true;
            var padding = (NameGrid.Width - MessagesListView.Height) / 2;

            MessagesListView.HeightRequest = MessagesLayoutFrame.Width;
            MessagesLayoutFrameInner.WidthRequest = MessagesLayoutFrame.Width;
            MessagesLayoutFrameInner.Padding = new Thickness(0);
            MessagesLayoutFrame.Padding = new Thickness(0);
            MessagesLayoutFrame.IsClippedToBounds = true;
            Xamarin.Forms.AbsoluteLayout.SetLayoutBounds(MessagesLayoutFrameInner, new Rectangle(0, 0 - padding, AbsoluteLayout.AutoSize, MessagesListView.Height - padding));
            MessagesLayoutFrameInner.IsClippedToBounds = true;
             // */
        } 
    }

WARNING НЕ ИСПОЛЬЗУЙТЕ <FRAMES> для макета, перемещающегося и вращающегося. Это потерпит крах на Windows Phone.

P.S Я уверен, что это может быть заключено в Nice UserControl, чтобы все могли его использовать.

10
Peter

Начиная с Xamarin Forms 2.3 CarouselView делает именно это, и даже больше. Читать дальше здесь .

<ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
  <CarouselView ItemsSource="{Binding MyDataSource}">
    <CarouselView.ItemTemplate>
      <DataTemplate>
        <Label Text="{Binding LabelText}" />
      </DataTemplate>
    </CarouselView.ItemTemplate>
  </CarouselView>
</ContentView>
8
Korayem

Как уже говорили другие, это невозможно с ListView, и я думаю, что Xamarin с Forms сильно упускает из виду. Нам нужно динамически отображать объекты, управляемые данными, не только в виде списка ... давай!

Однако в проекте Xamarin Labs есть GridView, который вы можете использовать. Это все еще немного грубо, и люди сейчас работают над некоторыми ошибками при выборе элементов.

https://github.com/XForms/Xamarin-Forms-Labs

У кого-то, кажется, есть решение этой проблемы:

https://github.com/XForms/Xamarin-Forms-Labs/issues/236

7
Daniel Nelson

Нет, горизонтального ListView нет. Вы можете обернуть горизонтальный StackLayout в горизонтальный ScrollView для достижения того же визуального результата, но это не совсем то же самое, поскольку у вас не будет DataTemplating.

6
Stephane Delcroix

Я не пробовал, но это может стоить проверить.

https://github.com/Cheesebaron/Cheesebaron.HorizontListView

3
Damien Sawyer

Я пробовал упомянутое «вращающееся» решение, и, помимо того, что оно «уродливое», оно также имеет несколько ограничений

  1. представление списка WidthRequest должно быть таким же, как HeightRequest
  2. высота строки listView больше не работает должным образом, потому что она становится шириной ячейки
  3. вертикальное выравнивание становится горизонтальным выравниванием и т. д., не очень поддерживаемое.

Лучшим вариантом является создание собственного пользовательского элемента управления или, как я это сделал, использование существующего HorizontalListView: https://www.nuget.org/packages/HorizontListView1.1/ Этот элемент легко использовать. Вы можете найти исходный код и документацию здесь

Реализация:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.Microsoft.com/winfx/2009/xaml" 
    x:Class="test.ListPage" 
    xmlns:Controls="clr-namespace:HorizontalList;Assembly=HorizontalList"> 

<Controls:HorizontalListView ItemsSource="{Binding Categories}" ListOrientation="Horizontal"> 
  <Controls:HorizontalListView.ItemTemplate> 
    <DataTemplate> 
    <Label Text="{Binding Name}" /> 
    </DataTemplate> 
  </Controls:HorizontalListView.ItemTemplate> 
  </Controls:HorizontalListView>
</ContentPage>
2
Niels

Этот пакет Nuget идеально подойдет для вашего случая. Я использовал это раньше, и мне действительно нравится это:

https://github.com/SuavePirate/DynamicStackLayout

Чтобы сделать вещи еще лучше, загрузите эти 3 пакета Nuget для загрузки, кэширования и преобразования изображений на своих фотографиях. Фотографии будут иметь форму круга, но этот нюгет имеет другие типы преобразований:

Xamarin.FFImageLoading (https://github.com/luberda-molinet/FFImageLoading/wiki/Xamarin.Forms-API)
Xamarin.FFImageLoading.Forms
Xamarin.FFImageLoading.Transformations (https://github.com/luberda-molinet/FFImageLoading/wiki/Transformations-Guide)

Вот фрагмент кода, который поможет вам начать: 

<!--Add this code to the top of your page-->
xmlns:ffimageloading="clr-namespace:FFImageLoading.Forms;Assembly=FFImageLoading.Forms"
xmlns:fftransformations="clr-namespace:FFImageLoading.Transformations;Assembly=FFImageLoading.Transformations"
xmlns:dynamicStackLayout="clr-namespace:SuaveControls.DynamicStackLayout;Assembly=SuaveControls.DynamicStackLayout"


<!-- Here is your control inside a ScrollView. The property Photos is a list of images address (Urls)  -->

<ScrollView Orientation="Horizontal" HorizontalOptions="FillAndExpand">
    <dynamicStackLayout:DynamicStackLayout ItemsSource="{Binding Photos}" HorizontalOptions="Fill" Orientation="Horizontal" Padding="10, -0, 100, 10">
        <dynamicStackLayout:DynamicStackLayout.ItemTemplate>
            <DataTemplate>
                <StackLayout BackgroundColor="Transparent" >
                    <ffimageloading:CachedImage HorizontalOptions="Start" VerticalOptions="Center" DownsampleToViewSize="true" Aspect="AspectFit" Source="{Binding .}">
                        <ffimageloading:CachedImage.GestureRecognizers>
                            <TapGestureRecognizer Command="{Binding Path=PhotoCommand}" CommandParameter="{Binding .}" NumberOfTapsRequired="1" />
                        </ffimageloading:CachedImage.GestureRecognizers>
                        <ffimageloading:CachedImage.HeightRequest>
                            <OnPlatform x:TypeArguments="x:Double">
                                <On Platform="iOS" Value="50" />
                                <On Platform="Android" Value="60" />
                            </OnPlatform>
                        </ffimageloading:CachedImage.HeightRequest>
                        <ffimageloading:CachedImage.WidthRequest>
                            <OnPlatform x:TypeArguments="x:Double">
                                <On Platform="iOS" Value="50" />
                                <On Platform="Android" Value="60" />
                            </OnPlatform>
                        </ffimageloading:CachedImage.WidthRequest>
                        <ffimageloading:CachedImage.Transformations>
                            <fftransformations:CircleTransformation BorderHexColor="#eeeeee">
                                <fftransformations:CircleTransformation.BorderSize>
                                    <OnPlatform x:TypeArguments="x:Double">
                                        <On Platform="iOS" Value="10" />
                                        <On Platform="Android" Value="10" />
                                    </OnPlatform>
                                </fftransformations:CircleTransformation.BorderSize>
                            </fftransformations:CircleTransformation>
                        </ffimageloading:CachedImage.Transformations>
                    </ffimageloading:CachedImage>
                </StackLayout>
            </DataTemplate>
        </dynamicStackLayout:DynamicStackLayout.ItemTemplate>
    </dynamicStackLayout:DynamicStackLayout>
</ScrollView>

Я надеюсь, что это помогает :)

2

Насколько я знаю, есть 3 способа реализовать это:

  1. Вращение ( как уже упоминали другие ребята )
    • Больше не нужно делать этот стандартный ListView
    • ItemTemplate доступен
    • Гадкое решение!
  2. Custom Render ( RecyclerView в Android и (я думаю) UICollectionView в iOS )
    • Доступна пользовательская ячейка (я уверен в Android, но не уверен в iOS)
    • Нужно больше работы и кода
  3. Сетка и Горизонтальное ScrollView ( использование горизонтального в качестве значения для ориентации в ScrollView )
    • Пользовательский макет доступен
    • В этом решении нет CachingStrategy, поэтому для большого списка это может привести к огромному использованию RAM для вашего приложения.
0
Mehdi Dehghani

В Xamarin.Forms 4.0-pre вы можете использовать CollectionView , что упрощает получение этого типа макета.

Образец:

<CollectionView ItemsSource="{Binding Monkeys}">
    <CollectionView.ItemsLayout>
        <ListItemsLayout>
            <x:Arguments>
                <ItemsLayoutOrientation>Horizontal</ItemsLayoutOrientation>    
            </x:Arguments>
        </ListItemsLayout>
    </CollectionView.ItemsLayout>
</CollectionView>
0
Bruno Caceiro

Пока CollectionView отсутствует, вы можете использовать мои Xamarin.Forms HorizontalListView .

Она имеет:

  • Привязка к первому или среднему элементу
  • Обивка и расстояние между предметами
  • Обрабатывает действия NotifyCollectionChangedAction по добавлению, удалению и сбросу
  • Просмотр утилизации
  • RecyclerView на Android
  • UICollectionView на iOS
  • Эта реализация на самом деле очень близка с точки зрения философии и реализации к тому, что обеспечит будущее Xamarin CollectionView.
0
Roubachof