Можно ли создать ListView
с horizontal scroll
в Xamarin.Forms
как изображение
это то, что я сделал для вертикального
var myListView = new ListView
{
ItemTemplate = new DataTemplate(typeof(ImageCell))
};
Можно ли создать ListView
с horizontal scroll
в Xamarin.Forms
как изображение
это то, что я сделал для вертикального
var myListView = new ListView
{
ItemTemplate = new DataTemplate(typeof(ImageCell))
};
Да, вы технически можете. Установите Rotation на 270 (все объекты VisualElements имеют свойство поворота 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>
Как и все остальные, No: в Xamarin.Forms отсутствует один доступный из коробки.
Однако - это не мешает кому-либо писать собственный пользовательский рендеринг для достижения такого типа управления.
Как упоминал Стефан Делкрукс, вы можете создать ScrollView, а затем StackLayout в качестве ребенка, чтобы создать тот же эффект.
Затем вам нужно реализовать: -
*), чтобы принять свойство (IEnumerable) ItemsSource, которое необходимо создать.
*), чтобы принять свойство (DataTemplate) ItemTemplate, которое необходимо создать.
*), чтобы создать экземпляр ItemTemplate, взяв конкретный элемент данных и превратив его в StackLayout. Вы также должны рассмотреть элементы, удаленные и т.д.
*) присоединить обработчики событий/жесты нажатия для выбора элемента.
*), реализующий выбранное состояние/дезактивацию других выбранных элементов.
... и т.д., чтобы получить полную реализацию.
Проблема со всем вышеизложенным заключается в том, что он подходит для относительно небольших списков элементов.
Однако, если вы ищете длинный список записей, то выше будет немного нежелательно, поскольку вы создаете все Представления.
Даже если вы задерживаете их загрузку, у вас все еще есть память для всех Представлений.
Затем это приводит к другой возможной реализации, которая касается виртуализированных элементов, что представляет собой совершенно другую историю, которую следует учитывать.
Как указывалось выше, стандартного способа сделать это не существует, однако существует способ его использования с использованием стандартного подхода ListView
и @MillieSmiths.
Для решения требуется несколько уровней вложенных макетов. Начиная с ListViewwe будет вращаться на 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;
// */
}
}
Внимание
НЕ ИСПОЛЬЗУЙТЕ <FRAMES>
для перемещения и вращения макета. Он сработает на Windows Phone.
P.S Я уверен, что это может быть завершено в приятном UserControl для всех, кто будет использовать.
Как и все остальные, невозможно с ListView, и я думаю, что это большой надзор со стороны Xamarin с помощью форм. Нам нужно динамически отображать объекты, управляемые данными, в большей степени, чем просто список, делающий вниз... давай, я! "
Однако в проекте Xamarin Labs есть GridView, который вы могли бы использовать. Это все еще немного грубо, и теперь люди просматривают некоторые ошибки при выборе элементов.
https://github.com/XForms/Xamarin-Forms-Labs
У кого-то, похоже, есть проблема с этой проблемой:
В отношении 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>
Нет, нет возможности иметь горизонтальный ListView
. Вы можете обернуть горизонтальный StackLayout в горизонтальном ScrollView для достижения того же визуального результата, но это не совсем то же самое, что и у вас не будет DataTemplating.
Я не пробовал, но это может стоить проверить.
https://github.com/Cheesebaron/Cheesebaron.HorizontalListView
Я попробовал упомянутое "вращающееся" решение, и, кроме того, это "уродливое" решение, оно также содержит несколько ограничений:
Лучшим вариантом является создание собственного пользовательского элемента управления или, как и я, использование существующего HorizontalListView: https://www.nuget.org/packages/HorizontalListView1.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>
Этот пакет 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>
Я надеюсь, что это помогает :)
Насколько я знаю, есть 3 способа реализовать это:
До выхода CollectionView вы можете использовать мой Xamarin.Forms HorizontalListView.
Она имеет:
Я использую это:
https://github.com/daniel-luberda/DLToolkit.Forms.Controls/tree/master/FlowListView
И я доволен результатами.
В Xamarin.Forms 4.0-pre вы можете использовать CollectionView, что упрощает получение этого типа макета.
Образец:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<ListItemsLayout>
<x:Arguments>
<ItemsLayoutOrientation>Horizontal</ItemsLayoutOrientation>
</x:Arguments>
</ListItemsLayout>
</CollectionView.ItemsLayout>
</CollectionView>
Это было решено с помощью специального класса под названием ItemsView (не путать с Xamarin ItemsView для шаблонов данных в ListView), который реализует шаблон ScrollView/StackPanel, упомянутый выше, для которого уже запрошен пример. Посмотрите код: https://gist.github.com/fonix232/b88412a976f67315f915