Ist eine Möglichkeit, ListView
mit horizontal scroll
inXamarin.Forms
wie Bild zu erstellen
das ist was ich für vertikal gemacht habe
var myListView = new ListView
{
ItemTemplate = new DataTemplate(typeof(ImageCell))
};
Ja, das kannst du technisch. Legen Sie die Rotation auf 270 fest (alle VisualElements haben eine Rotation BindableProperty). Dies sieht jedoch nach einer suboptimalen Lösung aus, da oben und unten weiße Räume vorhanden sind und Sie die Ansicht nach links und rechts ziehen müssen, um alles vollständig zu sehen.
public static readonly BindableProperty RotationProperty;
public static readonly BindableProperty RotationXProperty;
public static readonly BindableProperty RotationYProperty;
Der obige Code stammt aus der VisualElement-Klasse. Der folgende Code ist ein kleines Beispiel von mir.
∨∨∨
<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>
Wie alle anderen gesagt haben: Nein - in Xamarin.Forms ist kein Standardsatz verfügbar.
Es hält jedoch niemanden davon ab, seinen eigenen benutzerdefinierten Renderer zu schreiben, um diese Art der Steuerung zu erreichen.
Wie in Stephane Delcroix erwähnt, können Sie als Kind ein ScrollView und dann ein StackLayout erstellen, um denselben Effekt zu erzeugen.
Sie müssen dann Folgendes implementieren: -
*) bindable-Eigenschaft, um die (IEnumerable) ItemsSource -Eigenschaft anzunehmen, die erstellt werden muss.
*) bindable-Eigenschaft, um die (DataTemplate) ItemTemplate -Eigenschaft anzunehmen, die erstellt werden muss.
*) binding - Code, um Instanzen des ItemTemplate zu instanziieren, indem das bestimmte Datenquellenelement in das StackLayout gerendert wird. Sie müssen auch Elemente berücksichtigen, die entfernt wurden.
*) Fügen Sie Event-Handler/Tipp-Gesten für die Elementauswahl hinzu.
*) Implementieren eines ausgewählten Status/Deaktivieren anderer ausgewählter Elemente.
... und so weiter, um eine vollständige Implementierung zu erhalten.
Das Problem bei all dem oben genannten ist, dass es für relativ kleine Artikellisten geeignet ist.
Wenn Sie jedoch nach einer langen Liste von Einträgen suchen, wäre das oben etwas unerwünscht, da Sie alle Views upfront erstellen.
Auch wenn Sie verzögertes Laden von von diesen haben, müssen Sie immer noch den memory footprint aller Views beachten.
Dies führt dann zu einer anderen möglichen Implementierung, die sich mit Virtualized Items befasst, was eine völlig andere Geschichte ist.
Wie oben erwähnt, gibt es keine Standardmethode, jedoch gibt es eine Möglichkeit, die Standardvariablen ListView
und @MillieSmiths zu verwenden.
Die Lösung benötigt mehrere Ebenen verschachtelter Layouts. Wenn wir mit ListView beginnen, drehen wir diese um 270 Grad, was jedoch auch den Artikelinhalt dreht. Wir müssen diesen also um 90 Grad zurückdrehen.
Durch Drehen der ListView wird eine Menge Whitespace erzeugt. Durch das Einbetten der ListView in ein absolutes Layout können wir das lösen (wir benötigen eine zusätzliche Inhaltsansicht, um einige Beschneidungsprobleme zu beheben).
Schließlich müssen wir im Codebehind den Layoutausschnitt rendern
Seht die vollständige Lösung:
<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>
Für den Code dahinter müssen wir nur prüfen, ob wir die Dinge vorher eingerichtet haben. Grundsätzlich erfahren wir, wie breit die Seite ist (NameGrid
ist nur ein anderer Container mit voller Breite), dann verschieben Sie den direkten ListView-Container um die Hälfte des Whitespaces und schneiden ihn mit der anderen Hälfte unten ab.
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 VERWENDEN SIE NICHT <FRAMES>
für das Verschieben und Drehen des Layouts. Es wird unter Windows Phone abstürzen.
P.S Ich bin mir sicher, dass dies in einem Nice UserControl für jedermann eingepackt werden kann.
Ab Xamarin Forms 2.3 macht CarouselView
genau das und noch viel mehr. Lesen Sie mehr hier .
<ContentView HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<CarouselView ItemsSource="{Binding MyDataSource}">
<CarouselView.ItemTemplate>
<DataTemplate>
<Label Text="{Binding LabelText}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ContentView>
Wie die anderen schon sagten, mit ListView nicht möglich und ich denke, es ist ein großes Versehen von Xamarin mit Forms. Wir müssen datengesteuerte Objekte in mehr als nur einer Liste anzeigen lassen, die sich als unvollständig herausstellt.
Im Xamarin Labs-Projekt gibt es jedoch GridView, das Sie verwenden können. Es ist immer noch ein bisschen rau und die Leute arbeiten jetzt mit einigen Fehlern beim Auswählen der Elemente.
https://github.com/XForms/Xamarin-Forms-Labs
Jemand scheint dieses Problem zu umgehen:
Nein, es gibt keine Möglichkeit, ein horizontales ListView
zu haben. Sie können ein horizontales StackLayout in eine horizontale Bildlaufansicht umschließen, um das gleiche visuelle Ergebnis zu erzielen. Dies ist jedoch nicht ganz das gleiche, da Sie keine DataTemplating-Funktion haben.
Ich habe es nicht ausprobiert, aber es lohnt sich vielleicht.
https://github.com/Cheesebaron/Cheesebaron.HorizontalListView
Ich habe die erwähnte "rotierende" Lösung ausprobiert und abgesehen davon, dass es sich um eine "hässliche" Lösung handelt, gibt es auch einige Einschränkungen :
Eine bessere Option ist, ein eigenes benutzerdefiniertes Steuerelement zu erstellen oder, wie ich es getan habe, eine vorhandene HorizontalListView zu verwenden : https://www.nuget .org/packages/HorizontalListView1.1 / Diese ist einfach zu bedienen. Sie finden den Quellcode und die Dokumentation hier
Implementierung:
<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>
Dieses Nuget-Paket passt perfekt zu Ihrem Fall. Ich habe dieses schon einmal benutzt und ich mag es wirklich:
https://github.com/SuavePirate/DynamicStackLayout
Laden Sie diese 3 Nuget-Pakete herunter, um Bilder zu laden, zu cachen und umzuwandeln. Die Fotos werden in einem Kreis geformt, aber dieses Nuget hat andere Arten von Transformationen:
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)
Hier ist ein Code, der Ihnen beim Start helfen soll:
<!--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>
Ich hoffe, es hilft :)
Soweit ich weiß, gibt es drei Möglichkeiten, dies zu implementieren:
In Xamarin.Forms 4.0-pre können Sie die CollectionView verwenden, die das Erstellen dieser Art von Layout vereinfacht.
Probe:
<CollectionView ItemsSource="{Binding Monkeys}">
<CollectionView.ItemsLayout>
<ListItemsLayout>
<x:Arguments>
<ItemsLayoutOrientation>Horizontal</ItemsLayoutOrientation>
</x:Arguments>
</ListItemsLayout>
</CollectionView.ItemsLayout>
</CollectionView>
Bis das CollectionView out ist, können Sie meine Xamarin.Forms HorizontalListView verwenden.
Es hat: