Est-il possible de créer ListView
avec horizontal scroll
dansXamarin.Forms
like image
c'est ce que j'ai fait pour la verticale
var myListView = new ListView
{
ItemTemplate = new DataTemplate(typeof(ImageCell))
};
Oui, techniquement, vous le pouvez. Définissez la Rotation sur 270 (tous les VisualElements ont un Rotation BindableProperty). Cependant, cela ressemble à une solution sous-optimale car il y a des espaces blancs en haut et en bas et vous devez faire glisser la vue vers la gauche et la droite pour tout voir à fond.
public static readonly BindableProperty RotationProperty;
public static readonly BindableProperty RotationXProperty;
public static readonly BindableProperty RotationYProperty;
Le code ci-dessus provient de la classe VisualElement. Le code ci-dessous est un petit échantillon de mon propre.
∨∨∨
<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>
Comme tout le monde l’a dit, il n’existe pas de solution prête à l'emploi dans Xamarin.Forms .
Cependant, cela n’empêche personne d’écrire dans son propre moteur de rendu personnalisé pour obtenir ce type de contrôle.
Comme Stephane Delcroix l'a mentionné, vous pouvez créer un ScrollView puis un StackLayout en tant qu'enfant pour créer le même effet.
Vous devrez ensuite mettre en œuvre: -
*) propriété bindable pour accepter le (IEnumerable) ItemsSource propriété à créer.
*) propriété bindable pour accepter la propriété (DataTemplate) ItemTemplate qui doit être créée.
*) binding code pour instancier des instances de ItemTemplate en prenant l'élément de source de données spécifique et en le rendant dans StackLayout . Vous devez également tenir compte des éléments supprimés, etc.
*) attacher des gestionnaires d’événements/gestes tactiles pour la sélection d’éléments.
*) implémenter un état sélectionné/désactiver d'autres éléments sélectionnés.
... et ainsi de suite pour obtenir une mise en œuvre complète.
Le problème avec tout ce qui précède est qu’il convient aux listes d’articles relativement petites.
Cependant, si vous recherchez une longue liste d'entrées, ce qui est indiqué plus haut serait un peu indésirable, car vous créez toutes les Vues au début.
Même si vous retardez le chargement de ceux-ci, vous avez toujours la empreinte mémoire de tous les Vues à prendre en compte.
Cela conduit ensuite à une autre implémentation possible qui traite de Articles virtualisés , qui est une histoire complètement différente à considérer.
Comme indiqué ci-dessus, il n'y a pas de méthode standard pour ce faire, mais vous pouvez contourner le problème en utilisant une approche standard ListView
et @MillieSmiths.
La solution nécessite plusieurs couches de dispositions imbriquées. En commençant par ListView, nous pivoterons à 270 degrés, mais le contenu de notre article pivotera également; nous devons donc le faire pivoter de 90 degrés.
Faire pivoter le ListView crée énormément d’espace, en le plaçant dans une présentation absolue, nous pouvons le résoudre (nous avons besoin d’une vue de contenu supplémentaire afin de résoudre certains problèmes de découpage).
Enfin, dans le code ci-dessous, nous devons rendre le découpage de la mise en page
Voici la solution complète:
<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>
Pour le code sous-jacent, nous devons juste vérifier si nous avons déjà configuré les éléments, le cas échéant. En gros, nous découvrons quelle est la largeur de la page (NameGrid
n’est autre chose qu’un conteneur pleine largeur), puis nous déplaçons le conteneur ListView direct de moitié par rapport à l’espace vide et nous le découpons de l’autre moitié en bas.
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 NE PAS UTILISER <FRAMES>
pour la disposition en mouvement et en rotation. Il va planter sur Windows Phone.
P.S Je suis sûr que cela pourrait être résumé dans un Nice UserControl accessible à tous.
À partir de Xamarin Forms 2.3 CarouselView
fait exactement cela, et plus encore. Lire plus ici .
<ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<CarouselView ItemsSource="{Binding MyDataSource}">
<CarouselView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding LabelText}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ContentView>
Comme les autres l’ont dit, ce n’est pas possible avec ListView et j’estime que Xamarin avec Forms est un grand oubli. Nous avons besoin d'afficher dynamiquement des objets basés sur les données dans plus qu'une liste en bas ... allez-y !!
Cependant, dans le projet Xamarin Labs, vous pouvez utiliser GridView. C'est encore un peu rude et les gens essaient de résoudre certains problèmes en sélectionnant les éléments.
https://github.com/XForms/Xamarin-Forms-Labs
Quelqu'un semble avoir un moyen de contourner ce problème:
Non, il n'y a aucun moyen d'avoir une ListView
horizontale. Vous pouvez envelopper un StackLayout horizontal dans un ScrollView horizontal pour obtenir le même résultat visuel, mais ce n'est pas tout à fait pareil, car vous n'aurez pas de DataTemplating.
Je n'ai pas essayé, mais cela vaut peut-être la peine d'y aller.
https://github.com/Cheesebaron/Cheesebaron.HorizontalListView
J'ai essayé la solution "tournante" mentionnée et, outre qu'elle est une solution "laide", elle comporte également plusieurs limitations:
Une meilleure option consiste à créer votre propre contrôle personnalisé ou, comme je l’ai fait, utiliser un HorizontalListView existant: https://www.nuget.org/packages/HorizontalListView1.1/ Celui-ci est facile à utiliser. utilisation. Vous pouvez trouver le code source et la documentation ici
La mise en oeuvre:
<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>
Ce paquet de pépites conviendra parfaitement à votre cas. J'ai déjà utilisé celui-ci et je l'aime beaucoup:
https://github.com/SuavePirate/DynamicStackLayout
Pour rendre les choses encore mieux, téléchargez ces packages 3 Nuget pour charger, mettre en cache et transformer les images sur vos photos. Les photos seront en forme de cercle mais cette nuget a d'autres types de transformations:
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)
Voici un morceau de code pour vous aider à démarrer:
<!--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>
J'espère que ça aide :)
Pour autant que je sache, il y a 3 façons de mettre cela en œuvre:
Dans Xamarin.Forms 4.0-pre, vous pouvez utiliser CollectionView , ce qui simplifie l'obtention de ce type de présentation.
Échantillon:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<ListItemsLayout>
<x:Arguments>
<ItemsLayoutOrientation>Horizontal</ItemsLayoutOrientation>
</x:Arguments>
</ListItemsLayout>
</CollectionView.ItemsLayout>
</CollectionView>
Jusqu'à ce que CollectionView soit disponible, vous pouvez utiliser mon Xamarin.Forms HorizontalListView .
Il a: