web-dev-qa-db-fra.com

Liste horizontale Xamarin.Forms

Est-il possible de créer ListView avec horizontal scroll dansXamarin.Formslike image 

ListView Horizontal

c'est ce que j'ai fait pour la verticale 

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

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>
11
Millie Smith

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.

10
Pete

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.

10
Peter

À 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>
8
Korayem

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:

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

7
Daniel Nelson

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.

6
Stephane Delcroix

Je n'ai pas essayé, mais cela vaut peut-être la peine d'y aller.

https://github.com/Cheesebaron/Cheesebaron.HorizontalListView

3
Damien Sawyer

J'ai essayé la solution "tournante" mentionnée et, outre qu'elle est une solution "laide", elle comporte également plusieurs limitations

  1. la vue liste WidthRequest doit être identique à HeightRequest
  2. la hauteur de la ligne listView ne fonctionne plus correctement car elle devient la largeur de la cellule
  3. verticalalign devient horizontalalign, etc., peu maintenable.

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>
2
Niels

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:

  1. Rotation ( comme mentionné par d'autres gars )
    • Pas besoin de faire plus que ListView standard
    • ItemTemplate est disponible
    • Solution laide!
  2. Rendu personnalisé ( RecyclerView sous Android et (je pense) UICollectionView sous iOS )
    • La cellule personnalisée est disponible (je suis sûr pour Android, mais pas pour iOS)
    • Besoin de plus de travail et de code
  3. ScrollView Grille et Horizontal ( en utilisant horizontal comme valeur d'orientation prop dans ScrollView )
    • Une mise en page personnalisée est disponible
    • CachingStrategy n’existe pas dans cette solution. Par conséquent, une liste très longue risque d’engendrer une énorme RAM utilisation de votre application
0
Mehdi Dehghani

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>
0
Bruno Caceiro

Jusqu'à ce que CollectionView soit disponible, vous pouvez utiliser mon Xamarin.Forms HorizontalListView .

Il a:

  • Accrochage sur le premier ou le milieu
  • Rembourrage et espacement
  • Traite les actions Add, Remove et Reset de NotifyCollectionChangedAction
  • Voir le recyclage
  • RecyclerView sur Android
  • UICollectionView sur iOS
  • Cette implémentation est en fait très proche en termes de philosophie et d'implémentation de ce que fournira le futur Xamarin CollectionView.
0
Roubachof