Sammlungsansichten in Xamarin.iOS
Sammlungsansichten ermöglichen die Anzeige von Inhalten mit beliebigen Layouts. Sie ermöglichen das einfache Erstellen von rasterähnlichen Layouts außerhalb des Felds und unterstützen gleichzeitig benutzerdefinierte Layouts.
Sammlungsansichten, die in der UICollectionView
Klasse verfügbar sind, sind ein neues Konzept in iOS 6, das die Darstellung mehrerer Elemente auf dem Bildschirm mithilfe von Layouts eingeführt. Die Muster zum Bereitstellen von Daten für ein UICollectionView
Element zum Erstellen und Interagieren mit diesen Elementen folgen den gleichen Delegierungs- und Datenquellenmustern, die in der iOS-Entwicklung häufig verwendet werden.
Sammlungsansichten funktionieren jedoch mit einem Layoutsubsystem, das von sich selbst unabhängig UICollectionView
ist. Daher kann die Einfache Bereitstellung eines anderen Layouts die Darstellung einer Sammlungsansicht ganz einfach ändern.
iOS stellt eine Layoutklasse bereit, die es ermöglicht UICollectionViewFlowLayout
, zeilenbasierte Layouts wie z. B. ein Raster ohne zusätzliche Arbeit zu erstellen. Außerdem können benutzerdefinierte Layouts erstellt werden, die jede Präsentation zulassen, die Sie sich vorstellen können.
UICollectionView Basics
Die UICollectionView
Klasse besteht aus drei verschiedenen Elementen:
- Zellen – Datengesteuerte Ansichten für jedes Element
- Ergänzende Ansichten – Datengesteuerte Ansichten , die einem Abschnitt zugeordnet sind.
- Dekorationsansichten – Nicht datengesteuerte Ansichten, die durch ein Layout erstellt wurden
Zellen
Zellen sind Objekte, die ein einzelnes Element im Dataset darstellen, das von der Auflistungsansicht dargestellt wird. Jede Zelle ist eine Instanz der UICollectionViewCell
Klasse, die aus drei verschiedenen Ansichten besteht, wie in der folgenden Abbildung dargestellt:
Die UICollectionViewCell
Klasse verfügt über die folgenden Eigenschaften für jede dieser Ansichten:
ContentView
– Diese Ansicht enthält den Inhalt, den die Zelle darstellt. Sie wird in der obersten Z-Reihenfolge auf dem Bildschirm gerendert.SelectedBackgroundView
– Zellen haben unterstützung für die Auswahl integriert. Diese Ansicht wird verwendet, um visuell zu kennzeichnen, dass eine Zelle ausgewählt ist. Sie wird direkt unterhalb derContentView
Zelle gerendert, wenn eine Zelle ausgewählt wird.BackgroundView
– Zellen können auch einen Hintergrund anzeigen, der von derBackgroundView
. Diese Ansicht wird unter derSelectedBackgroundView
.
Durch Festlegen derArt ContentView
, dass sie kleiner als die BackgroundView
und SelectedBackgroundView
ist, kann dies verwendet werden, um den BackgroundView
Inhalt visuell zu framen, während die SelectedBackgroundView
Anzeige erfolgt, wenn eine Zelle ausgewählt wird, wie unten dargestellt:
Die Zellen im obigen Screenshot werden erstellt, indem sie erben UICollectionViewCell
und die ContentView
Eigenschaften SelectedBackgroundView
BackgroundView
bzw. Eigenschaften festlegen, wie im folgenden Code gezeigt:
public class AnimalCell : UICollectionViewCell
{
UIImageView imageView;
[Export ("initWithFrame:")]
public AnimalCell (CGRect frame) : base (frame)
{
BackgroundView = new UIView{BackgroundColor = UIColor.Orange};
SelectedBackgroundView = new UIView{BackgroundColor = UIColor.Green};
ContentView.Layer.BorderColor = UIColor.LightGray.CGColor;
ContentView.Layer.BorderWidth = 2.0f;
ContentView.BackgroundColor = UIColor.White;
ContentView.Transform = CGAffineTransform.MakeScale (0.8f, 0.8f);
imageView = new UIImageView (UIImage.FromBundle ("placeholder.png"));
imageView.Center = ContentView.Center;
imageView.Transform = CGAffineTransform.MakeScale (0.7f, 0.7f);
ContentView.AddSubview (imageView);
}
public UIImage Image {
set {
imageView.Image = value;
}
}
}
Ergänzende Ansichten
Ergänzende Ansichten sind Ansichten, die Informationen enthalten, die den einzelnen Abschnitten eines Abschnitts UICollectionView
zugeordnet sind. Wie Zellen sind ergänzende Ansichten datengesteuert. Wenn Zellen die Elementdaten aus einer Datenquelle darstellen, stellen ergänzende Ansichten die Abschnittsdaten dar, z. B. die Kategorien des Buchs in einem Bücherhelf oder das Musikgenre in einer Musikbibliothek.
Beispielsweise könnte eine ergänzende Ansicht verwendet werden, um eine Kopfzeile für einen bestimmten Abschnitt darzustellen, wie in der folgenden Abbildung dargestellt:
Um eine ergänzende Ansicht zu verwenden, muss sie zuerst in der ViewDidLoad
Methode registriert werden:
CollectionView.RegisterClassForSupplementaryView (typeof(Header), UICollectionElementKindSection.Header, headerId);
Anschließend muss die Ansicht mithilfe GetViewForSupplementaryElement
von , erstellt mit DequeueReusableSupplementaryView
und erbt von UICollectionReusableView
. Der folgende Codeausschnitt erzeugt die im Obigen Screenshot gezeigte Ergänzungsansicht:
public override UICollectionReusableView GetViewForSupplementaryElement (UICollectionView collectionView, NSString elementKind, NSIndexPath indexPath)
{
var headerView = (Header)collectionView.DequeueReusableSupplementaryView (elementKind, headerId, indexPath);
headerView.Text = "Supplementary View";
return headerView;
}
Ergänzende Ansichten sind allgemeiner als nur Kopf- und Fußzeilen. Sie können an einer beliebigen Stelle in der Sammlungsansicht positioniert werden und können aus allen Ansichten bestehen, wodurch ihre Darstellung vollständig angepasst werden kann.
Dekoration Ansichten
Dekorationsansichten sind rein visuelle Ansichten, die in einer UICollectionView
. Im Gegensatz zu Zellen und ergänzenden Ansichten sind sie nicht datengesteuert. Sie werden immer in der Unterklasse eines Layouts erstellt und können sich anschließend als Layout des Inhalts ändern. Beispielsweise könnte eine Dekorationsansicht verwendet werden, um eine Hintergrundansicht darzustellen, die mit dem Inhalt in der UICollectionView
Abbildung scrollt, wie unten dargestellt:
Der folgende Codeausschnitt ändert den Hintergrund in der Beispielklasse CircleLayout
in Rot:
public class MyDecorationView : UICollectionReusableView
{
[Export ("initWithFrame:")]
public MyDecorationView (CGRect frame) : base (frame)
{
BackgroundColor = UIColor.Red;
}
}
Data source
Wie bei anderen Teilen von iOS, z UITableView
. B. und MKMapView
, UICollectionView
ruft seine Daten aus einer Datenquelle ab, die in Xamarin.iOS über die UICollectionViewDataSource
Klasse verfügbar gemacht wird. Diese Klasse ist für die Bereitstellung von Inhalten für folgendes UICollectionView
verantwortlich:
- Zellen – Wird von
GetCell
der Methode zurückgegeben. - Ergänzende Ansichten – Wird von
GetViewForSupplementaryElement
der Methode zurückgegeben. - Anzahl der Abschnitte – Von
NumberOfSections
der Methode zurückgegeben. Standardwert ist 1, wenn sie nicht implementiert ist. - Anzahl der Elemente pro Abschnitt – Von
GetItemsCount
der Methode zurückgegeben.
UICollectionViewController
Zur Bequemlichkeit ist die UICollectionViewController
Klasse verfügbar. Dies wird automatisch so konfiguriert, dass es sich um die Stellvertretung handelt, die im nächsten Abschnitt erläutert wird, und als Datenquelle für die UICollectionView
Ansicht.
Wie bei UITableView
der Klasse UICollectionView
wird die Datenquelle nur aufgerufen, um Zellen für Elemente abzurufen, die sich auf dem Bildschirm befinden.
Zellen, die auf dem Bildschirm scrollen, werden zur Wiederverwendung in eine Warteschlange eingefügt, wie die folgende Abbildung veranschaulicht:
Die Zellwiederverwendung wurde vereinfacht mit UICollectionView
und UITableView
. Sie müssen eine Zelle nicht mehr direkt in der Datenquelle erstellen, wenn sie in der Wiederverwendungswarteschlange nicht verfügbar ist, da Zellen beim System registriert sind. Wenn eine Zelle nicht verfügbar ist, wenn der Aufruf der Zelle aus der Wiederverwendungswarteschlange entfernt wird, erstellt iOS sie automatisch basierend auf dem registrierten Typ oder Nib.
Das gleiche Verfahren steht auch für ergänzende Ansichten zur Verfügung.
Betrachten Sie beispielsweise den folgenden Code, der die AnimalCell
Klasse registriert:
static NSString animalCellId = new NSString ("AnimalCell");
CollectionView.RegisterClassForCell (typeof(AnimalCell), animalCellId);
Wenn eine UICollectionView
Zelle benötigt wird, da sich das Element auf dem Bildschirm befindet, ruft die UICollectionView
Methode der GetCell
Datenquelle auf. Ähnlich wie bei UITableView ist diese Methode für die Konfiguration einer Zelle aus den Sicherungsdaten verantwortlich, was in diesem Fall eine AnimalCell
Klasse wäre.
Der folgende Code zeigt eine Implementierung, die GetCell
eine AnimalCell
Instanz zurückgibt:
public override UICollectionViewCell GetCell (UICollectionView collectionView, Foundation.NSIndexPath indexPath)
{
var animalCell = (AnimalCell)collectionView.DequeueReusableCell (animalCellId, indexPath);
var animal = animals [indexPath.Row];
animalCell.Image = animal.Image;
return animalCell;
}
Der Anruf an DequeReusableCell
den Ort, an dem die Zelle entweder aus der Wiederverwendungswarteschlange in die Warteschlange eingereiht wird oder, wenn eine Zelle nicht in der Warteschlange verfügbar ist, basierend auf dem Typ erstellt wird, der im Anruf CollectionView.RegisterClassForCell
registriert ist.
In diesem Fall erstellt iOS durch die Registrierung der AnimalCell
Klasse eine neue AnimalCell
intern und gibt sie zurück, wenn ein Aufruf der De-Warteschlange eine Zelle erfolgt, nach der sie mit dem In der Tierklasse enthaltenen Bild konfiguriert und zur Anzeige an die UICollectionView
Zurückgegeben wird.
Delegieren
Die UICollectionView
Klasse verwendet einen Delegat vom Typ UICollectionViewDelegate
, um die Interaktion mit Inhalten in der UICollectionView
. Dies ermöglicht die Steuerung von:
- Zellauswahl – Bestimmt, ob eine Zelle ausgewählt ist.
- Zellmarkierung – Bestimmt, ob eine Zelle gerade berührt wird.
- Zellmenüs – Menü, das als Reaktion auf eine lange Druckgeste für eine Zelle angezeigt wird.
Wie bei der Datenquelle ist dies UICollectionViewController
standardmäßig als Stellvertretung für die UICollectionView
.
Zellen highLighting
Wenn eine Zelle gedrückt wird, wechselt die Zelle in einen hervorgehobenen Zustand, und sie wird erst ausgewählt, wenn der Benutzer seinen Finger von der Zelle hebt. Dies ermöglicht eine temporäre Änderung der Darstellung der Zelle, bevor sie tatsächlich ausgewählt wird. Nach auswahl wird die Zelle SelectedBackgroundView
angezeigt. Die folgende Abbildung zeigt den hervorgehobenen Zustand unmittelbar vor dem Auftreten der Auswahl:
Um hervorhebungen zu implementieren, können die ItemHighlighted
Methoden und ItemUnhighlighted
Methoden der UICollectionViewDelegate
Anwendung verwendet werden. Der folgende Code wendet z. B. einen gelben Hintergrund an ContentView
, wenn die Zelle hervorgehoben ist, und einen weißen Hintergrund, wenn er nicht hervorgehoben wird, wie in der abbildung oben gezeigt:
public override void ItemHighlighted (UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = collectionView.CellForItem(indexPath);
cell.ContentView.BackgroundColor = UIColor.Yellow;
}
public override void ItemUnhighlighted (UICollectionView collectionView, NSIndexPath indexPath)
{
var cell = collectionView.CellForItem(indexPath);
cell.ContentView.BackgroundColor = UIColor.White;
}
Deaktivieren der Auswahl
Die Auswahl ist standardmäßig in UICollectionView
. Um die Auswahl zu deaktivieren, setzen Sie "false" außer Kraft ShouldHighlightItem
, und geben Sie "false" zurück, wie unten dargestellt:
public override bool ShouldHighlightItem (UICollectionView collectionView, NSIndexPath indexPath)
{
return false;
}
Wenn die Hervorhebung deaktiviert ist, wird auch der Vorgang zum Auswählen einer Zelle deaktiviert. Darüber hinaus gibt es auch eine ShouldSelectItem
Methode, mit der die Auswahl direkt gesteuert wird, auch wenn ShouldHighlightItem
diese implementiert und "false" zurückgegeben wird, ShouldSelectItem
nicht aufgerufen wird.
ShouldSelectItem
ermöglicht das Aktivieren oder Deaktivieren der Auswahl auf Element-nach-Element-Basis, wenn ShouldHighlightItem
sie nicht implementiert ist. Sie ermöglicht auch die Hervorhebung ohne Auswahl, wenn ShouldHighlightItem
sie implementiert ist und "true" zurückgibt, während ShouldSelectItem
"false" zurückgegeben wird.
Zellmenüs
Jede Zelle in einer UICollectionView
Zelle kann ein Menü anzeigen, das das Ausschneiden, Kopieren und Einfügen optional unterstützt. So erstellen Sie ein Bearbeitungsmenü in einer Zelle:
- Überschreiben
ShouldShowMenu
und zurückgeben "true", wenn das Element ein Menü anzeigen soll. - Überschreiben
CanPerformAction
sie und geben "true" für jede Aktion zurück, die das Element ausführen kann. Dabei handelt es sich um einen Ausschneiden, Kopieren oder Einfügen. - Überschreiben
PerformAction
, um die Bearbeitung, kopieren des Einfügevorgangs auszuführen.
Der folgende Screenshot zeigt das Menü, wenn eine Zelle lang gedrückt wird:
Layout
UICollectionView
unterstützt ein Layoutsystem, das die Positionierung aller Elemente, Zellen, Ergänzende Ansichten und Dekorationsansichten ermöglicht, unabhängig vom UICollectionView
selbst verwaltet zu werden.
Mithilfe des Layoutsystems kann eine Anwendung Layouts wie das rasterähnliche Layout unterstützen, das wir in diesem Artikel gesehen haben, sowie benutzerdefinierte Layouts bereitstellen.
Layoutgrundlagen
Layouts in a UICollectionView
werden in einer Klasse definiert, von UICollectionViewLayout
der geerbt wird. Die Layoutimplementierung ist für das Erstellen der Layoutattribute für jedes Element in der UICollectionView
. Es gibt zwei Möglichkeiten zum Erstellen eines Layouts:
- Verwenden Sie die integrierte
UICollectionViewFlowLayout
. - Stellen Sie ein benutzerdefiniertes Layout bereit, indem Sie von
UICollectionViewLayout
.
Flusslayout
Die UICollectionViewFlowLayout
Klasse bietet ein linienbasiertes Layout, das zum Anordnen von Inhalten in einem Raster von Zellen geeignet ist, wie wir gesehen haben.
So verwenden Sie ein Flusslayout:
- Erstellen einer Instanz von
UICollectionViewFlowLayout
:
var layout = new UICollectionViewFlowLayout ();
- Übergeben Sie die Instanz an den Konstruktor der
UICollectionView
:
simpleCollectionViewController = new SimpleCollectionViewController (layout);
Dies ist alles, was zum Layout von Inhalten in einem Raster erforderlich ist. Wenn sich die Ausrichtung ändert, werden die UICollectionViewFlowLayout
Ziehpunkte auch entsprechend anordnen, wie unten dargestellt:
Abschnittseinbruch
Um Platz um die UIContentView
Layouts bereitzustellen, weisen sie eine SectionInset
Eigenschaft vom Typ UIEdgeInsets
auf. Der folgende Code stellt beispielsweise einen 50-Pixel-Puffer um jeden Abschnitt des UIContentView
durch ein UICollectionViewFlowLayout
:
var layout = new UICollectionViewFlowLayout ();
layout.SectionInset = new UIEdgeInsets (50,50,50,50);
Dies führt zu Abständen um den Abschnitt, wie unten dargestellt:
Unterklassen von UICollectionViewFlowLayout
In edition to using UICollectionViewFlowLayout
directly, it can also be subclassed to further customize the layout of content along a line. Dies kann beispielsweise verwendet werden, um ein Layout zu erstellen, das die Zellen nicht in ein Raster umschließt, sondern stattdessen eine einzelne Zeile mit einem horizontalen Bildlaufeffekt erstellt, wie unten dargestellt:
Um dies durch Unterklassen UICollectionViewFlowLayout
zu implementieren, ist Folgendes erforderlich:
- Initialisieren sie alle Layouteigenschaften, die auf das Layout selbst oder alle Elemente im Layout im Konstruktor angewendet werden.
- Überschreiben,
ShouldInvalidateLayoutForBoundsChange
"true" zurückgeben, sodass beim ÄndernUICollectionView
das Layout der Zellen neu berechnet wird. Dies wird in diesem Fall verwendet, um sicherzustellen, dass der Code für die Transformation, die auf die zentriertste Zelle angewendet wird, während des Bildlaufs angewendet wird. - Überschreiben,
TargetContentOffset
damit die zentriertste Zelle an der Mitte desUICollectionView
Bildlaufstopps ausgerichtet wird. - Überschreiben
LayoutAttributesForElementsInRect
, um ein Array von zurückzugeben.UICollectionViewLayoutAttributes
JedeUICollectionViewLayoutAttribute
enthält Informationen zum Layout des jeweiligen Elements, einschließlich Eigenschaften wie derenCenter
,Size
ZIndex
undTransform3D
.
Der folgende Code zeigt eine solche Implementierung:
using System;
using CoreGraphics;
using Foundation;
using UIKit;
using CoreGraphics;
using CoreAnimation;
namespace SimpleCollectionView
{
public class LineLayout : UICollectionViewFlowLayout
{
public const float ITEM_SIZE = 200.0f;
public const int ACTIVE_DISTANCE = 200;
public const float ZOOM_FACTOR = 0.3f;
public LineLayout ()
{
ItemSize = new CGSize (ITEM_SIZE, ITEM_SIZE);
ScrollDirection = UICollectionViewScrollDirection.Horizontal;
SectionInset = new UIEdgeInsets (400,0,400,0);
MinimumLineSpacing = 50.0f;
}
public override bool ShouldInvalidateLayoutForBoundsChange (CGRect newBounds)
{
return true;
}
public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (CGRect rect)
{
var array = base.LayoutAttributesForElementsInRect (rect);
var visibleRect = new CGRect (CollectionView.ContentOffset, CollectionView.Bounds.Size);
foreach (var attributes in array) {
if (attributes.Frame.IntersectsWith (rect)) {
float distance = (float)(visibleRect.GetMidX () - attributes.Center.X);
float normalizedDistance = distance / ACTIVE_DISTANCE;
if (Math.Abs (distance) < ACTIVE_DISTANCE) {
float zoom = 1 + ZOOM_FACTOR * (1 - Math.Abs (normalizedDistance));
attributes.Transform3D = CATransform3D.MakeScale (zoom, zoom, 1.0f);
attributes.ZIndex = 1;
}
}
}
return array;
}
public override CGPoint TargetContentOffset (CGPoint proposedContentOffset, CGPoint scrollingVelocity)
{
float offSetAdjustment = float.MaxValue;
float horizontalCenter = (float)(proposedContentOffset.X + (this.CollectionView.Bounds.Size.Width / 2.0));
CGRect targetRect = new CGRect (proposedContentOffset.X, 0.0f, this.CollectionView.Bounds.Size.Width, this.CollectionView.Bounds.Size.Height);
var array = base.LayoutAttributesForElementsInRect (targetRect);
foreach (var layoutAttributes in array) {
float itemHorizontalCenter = (float)layoutAttributes.Center.X;
if (Math.Abs (itemHorizontalCenter - horizontalCenter) < Math.Abs (offSetAdjustment)) {
offSetAdjustment = itemHorizontalCenter - horizontalCenter;
}
}
return new CGPoint (proposedContentOffset.X + offSetAdjustment, proposedContentOffset.Y);
}
}
}
Benutzerdefiniertes Layout
Zusätzlich zur Verwendung UICollectionViewFlowLayout
können Layouts auch vollständig angepasst werden, indem sie direkt von UICollectionViewLayout
.
Die wichtigsten Methoden zum Außerkraftsetzen sind:
PrepareLayout
– Wird für die Durchführung anfänglicher geometrischer Berechnungen verwendet, die während des gesamten Layoutprozesses verwendet werden.CollectionViewContentSize
– Gibt die Größe des Bereichs zurück, der zum Anzeigen von Inhalten verwendet wird.LayoutAttributesForElementsInRect
– Wie bereits im oben gezeigten Beispiel für UICollectionViewFlowLayout wird diese Methode verwendet, um Informationen zumUICollectionView
Layout der einzelnen Elemente bereitzustellen. Im Gegensatz zumUICollectionViewFlowLayout
Erstellen eines benutzerdefinierten Layouts können Sie elemente jedoch bei der Auswahl positionieren.
Beispielsweise könnte der gleiche Inhalt in einem kreisförmigen Layout dargestellt werden, wie unten gezeigt:
Das Leistungsstarke an Layouts besteht darin, dass zum Wechseln vom rasterähnlichen Layout zu einem horizontalen Bildlauflayout und anschließend zu diesem kreisförmigen Layout nur die Layoutklasse erforderlich ist, die für die UICollectionView
Änderung bereitgestellt wird. Nichts im UICollectionView
Stellvertretungs- oder Datenquellencode ändert sich überhaupt.
Änderungen in iOS 9
In iOS 9 unterstützt die Sammlungsansicht (UICollectionView
) jetzt das Neuanordnen von Elementen aus dem Feld, indem eine neue Standardgestenerkennung und mehrere neue Unterstützende Methoden hinzugefügt werden.
Mithilfe dieser neuen Methoden können Sie das Ziehen ganz einfach implementieren, um sie in der Sammlungsansicht neu anzuordnen und die Möglichkeit haben, die Darstellung der Elemente während einer beliebigen Phase des Neuanordnungsprozesses anzupassen.
In diesem Artikel befassen wir uns mit der Implementierung von Drag-to-Reorder in einer Xamarin.iOS-Anwendung sowie mit einigen der anderen Änderungen, die iOS 9 am Steuerelement für die Sammlungsansicht vorgenommen hat:
Neuanordnung von Elementen
Wie bereits erwähnt, war eine der wichtigsten Änderungen an der Sammlungsansicht in iOS 9 das Hinzufügen einfacher Funktionen zum Neuanordnen von Ziehvorgängen.
In iOS 9 besteht die schnellste Möglichkeit zum Hinzufügen der Neuanordnung zu einer Sammlungsansicht darin, eine UICollectionViewController
.
Der Sammlungsansichtscontroller verfügt jetzt über eine InstallsStandardGestureForInteractiveMovement
Eigenschaft, die eine Standardgestenerkennung hinzufügt, die das Ziehen zum Neuanordnen von Elementen in der Auflistung unterstützt.
Da der Standardwert lautet true
, müssen Sie nur die MoveItem
Methode der UICollectionViewDataSource
Klasse implementieren, um drag-to-reorder zu unterstützen. Zum Beispiel:
public override void MoveItem (UICollectionView collectionView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
{
// Reorder our list of items
...
}
Beispiel für einfache Neuanordnung
Beginnen Sie als schnelles Beispiel ein neues Xamarin.iOS-Projekt, und bearbeiten Sie die Datei "Main.storyboard" . Ziehen Sie ein Shape UICollectionViewController
auf die Entwurfsoberfläche:
Wählen Sie die Sammlungsansicht aus (Dies ist möglicherweise am einfachsten in der Dokumentgliederung möglich). Legen Sie auf der Registerkarte "Layout" des Eigenschaftenpads die folgenden Größen fest, wie im folgenden Screenshot dargestellt:
- Zellengröße: Breite – 60 | Höhe – 60
- Kopfzeilengröße: Breite – 0 | Höhe – 0
- Fußzeilengröße: Breite – 0 | Höhe – 0
- Min Abstand: Für Zellen – 8 | Für Linien – 8
- Abschnittsmengen: Top – 16 | Unten – 16 | Links – 16 | Rechts – 16
Bearbeiten Sie als Nächstes die Standardzelle:
- Ändern der Hintergrundfarbe in Blau
- Hinzufügen einer Beschriftung, die als Titel für die Zelle fungiert
- Festlegen des Wiederverwendungsbezeichners auf Zelle
Fügen Sie Einschränkungen hinzu, um die Beschriftung innerhalb der Zelle zentriert zu halten, während sich die Größe ändert:
Legen Sie im Property Pad für collectionViewCell die Klasse auf :TextCollectionViewCell
Legen Sie die wiederverwendbare Sammlungsansicht auf Cell
:
Wählen Sie schließlich das Etikett aus, und nennen Sie es TextLabel
:
Bearbeiten Sie die TextCollectionViewCell
Klasse, und fügen Sie die folgenden Eigenschaften hinzu:
using System;
using Foundation;
using UIKit;
namespace CollectionView
{
public partial class TextCollectionViewCell : UICollectionViewCell
{
#region Computed Properties
public string Title {
get { return TextLabel.Text; }
set { TextLabel.Text = value; }
}
#endregion
#region Constructors
public TextCollectionViewCell (IntPtr handle) : base (handle)
{
}
#endregion
}
}
Hier wird die Text
Eigenschaft der Beschriftung als Titel der Zelle verfügbar gemacht, sodass sie aus Code festgelegt werden kann.
Fügen Sie dem Projekt eine neue C#-Klasse hinzu, und rufen Sie sie WaterfallCollectionSource
auf. Bearbeiten Sie die Datei, und stellen Sie sicher, dass sie wie folgt aussieht:
using System;
using Foundation;
using UIKit;
using System.Collections.Generic;
namespace CollectionView
{
public class WaterfallCollectionSource : UICollectionViewDataSource
{
#region Computed Properties
public WaterfallCollectionView CollectionView { get; set;}
public List<int> Numbers { get; set; } = new List<int> ();
#endregion
#region Constructors
public WaterfallCollectionSource (WaterfallCollectionView collectionView)
{
// Initialize
CollectionView = collectionView;
// Init numbers collection
for (int n = 0; n < 100; ++n) {
Numbers.Add (n);
}
}
#endregion
#region Override Methods
public override nint NumberOfSections (UICollectionView collectionView) {
// We only have one section
return 1;
}
public override nint GetItemsCount (UICollectionView collectionView, nint section) {
// Return the number of items
return Numbers.Count;
}
public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
// Get a reusable cell and set {~~it's~>its~~} title from the item
var cell = collectionView.DequeueReusableCell ("Cell", indexPath) as TextCollectionViewCell;
cell.Title = Numbers [(int)indexPath.Item].ToString();
return cell;
}
public override bool CanMoveItem (UICollectionView collectionView, NSIndexPath indexPath) {
// We can always move items
return true;
}
public override void MoveItem (UICollectionView collectionView, NSIndexPath sourceIndexPath, NSIndexPath destinationIndexPath)
{
// Reorder our list of items
var item = Numbers [(int)sourceIndexPath.Item];
Numbers.RemoveAt ((int)sourceIndexPath.Item);
Numbers.Insert ((int)destinationIndexPath.Item, item);
}
#endregion
}
}
Diese Klasse ist die Datenquelle für unsere Sammlungsansicht und stellt die Informationen für jede Zelle in der Sammlung bereit.
Beachten Sie, dass die MoveItem
Methode implementiert ist, damit Elemente in der Auflistung neu angeordnet werden können.
Fügen Sie dem Projekt eine weitere neue C#-Klasse hinzu, und rufen Sie sie WaterfallCollectionDelegate
auf. Bearbeiten Sie diese Datei, und sehen Sie wie folgt aus:
using System;
using Foundation;
using UIKit;
using System.Collections.Generic;
namespace CollectionView
{
public class WaterfallCollectionDelegate : UICollectionViewDelegate
{
#region Computed Properties
public WaterfallCollectionView CollectionView { get; set;}
#endregion
#region Constructors
public WaterfallCollectionDelegate (WaterfallCollectionView collectionView)
{
// Initialize
CollectionView = collectionView;
}
#endregion
#region Overrides Methods
public override bool ShouldHighlightItem (UICollectionView collectionView, NSIndexPath indexPath) {
// Always allow for highlighting
return true;
}
public override void ItemHighlighted (UICollectionView collectionView, NSIndexPath indexPath)
{
// Get cell and change to green background
var cell = collectionView.CellForItem(indexPath);
cell.ContentView.BackgroundColor = UIColor.FromRGB(183,208,57);
}
public override void ItemUnhighlighted (UICollectionView collectionView, NSIndexPath indexPath)
{
// Get cell and return to blue background
var cell = collectionView.CellForItem(indexPath);
cell.ContentView.BackgroundColor = UIColor.FromRGB(164,205,255);
}
#endregion
}
}
Dies dient als Stellvertretung für unsere Sammlungsansicht. Methoden wurden außer Kraft gesetzt, um eine Zelle hervorzuheben, während der Benutzer in der Auflistungsansicht damit interagiert.
Fügen Sie dem Projekt eine letzte C#-Klasse hinzu, und rufen Sie sie WaterfallCollectionView
auf. Bearbeiten Sie diese Datei, und sehen Sie wie folgt aus:
using System;
using UIKit;
using System.Collections.Generic;
using Foundation;
namespace CollectionView
{
[Register("WaterfallCollectionView")]
public class WaterfallCollectionView : UICollectionView
{
#region Constructors
public WaterfallCollectionView (IntPtr handle) : base (handle)
{
}
#endregion
#region Override Methods
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Initialize
DataSource = new WaterfallCollectionSource(this);
Delegate = new WaterfallCollectionDelegate(this);
}
#endregion
}
}
Beachten Sie, dass DataSource
und Delegate
dass wir oben erstellt werden, wenn die Sammlungsansicht aus dem Storyboard (oder XIB-Datei ) erstellt wird.
Bearbeiten Sie die Datei "Main.storyboard " erneut, und wählen Sie die Sammlungsansicht aus, und wechseln Sie zu den Eigenschaften. Legen Sie die Klasse auf die benutzerdefinierte WaterfallCollectionView
Klasse fest, die wir oben definiert haben:
Speichern Sie die Änderungen, die Sie an der Benutzeroberfläche vorgenommen haben, und führen Sie die App aus. Wenn der Benutzer ein Element aus der Liste auswählt und es an eine neue Position zieht, werden die anderen Elemente automatisch animiert, wenn sie sich aus dem Weg des Elements bewegen. Wenn der Benutzer das Element an einer neuen Position abbricht, bleibt es an dieser Position. Zum Beispiel:
Verwenden einer benutzerdefinierten Gestikerkennung
In Fällen, in denen Sie kein reguläres UICollectionViewController
Steuerelement verwenden können und ein reguläres UIViewController
Element verwenden müssen, oder wenn Sie mehr Kontrolle über die Zieh- und Drop-Geste übernehmen möchten, können Sie eine eigene benutzerdefinierte Gestenerkennung erstellen und sie der Sammlungsansicht hinzufügen, wenn die Ansicht geladen wird. Zum Beispiel:
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Create a custom gesture recognizer
var longPressGesture = new UILongPressGestureRecognizer ((gesture) => {
// Take action based on state
switch(gesture.State) {
case UIGestureRecognizerState.Began:
var selectedIndexPath = CollectionView.IndexPathForItemAtPoint(gesture.LocationInView(View));
if (selectedIndexPath !=null) {
CollectionView.BeginInteractiveMovementForItem(selectedIndexPath);
}
break;
case UIGestureRecognizerState.Changed:
CollectionView.UpdateInteractiveMovementTargetPosition(gesture.LocationInView(View));
break;
case UIGestureRecognizerState.Ended:
CollectionView.EndInteractiveMovement();
break;
default:
CollectionView.CancelInteractiveMovement();
break;
}
});
// Add the custom recognizer to the collection view
CollectionView.AddGestureRecognizer(longPressGesture);
}
Hier verwenden wir mehrere neue Methoden, die der Sammlungsansicht hinzugefügt wurden, um den Ziehvorgang zu implementieren und zu steuern:
BeginInteractiveMovementForItem
– Markiert den Anfang eines Verschiebungsvorgangs.UpdateInteractiveMovementTargetPosition
- Wird gesendet, wenn der Speicherort des Elements aktualisiert wird.EndInteractiveMovement
- Markiert das Ende einer Elementverschiebung.CancelInteractiveMovement
– Markiert den Benutzer, der den Verschiebungsvorgang abbricht.
Wenn die Anwendung ausgeführt wird, funktioniert der Ziehvorgang genau wie die standardmäßige Ziehgestenerkennung, die im Lieferumfang der Sammlungsansicht enthalten ist.
Benutzerdefinierte Layouts und Neuanordnung
In iOS 9 wurden mehrere neue Methoden hinzugefügt, um mit Drag-to-Reorder- und benutzerdefinierten Layouts in einer Sammlungsansicht zu arbeiten. Um dieses Feature zu erkunden, fügen wir der Sammlung ein benutzerdefiniertes Layout hinzu.
Fügen Sie zunächst eine neue C#-Klasse hinzu, die dem Projekt aufgerufen wird WaterfallCollectionLayout
. Bearbeiten Sie sie, und stellen Sie sicher, dass sie wie folgt aussieht:
using System;
using Foundation;
using UIKit;
using System.Collections.Generic;
using CoreGraphics;
namespace CollectionView
{
[Register("WaterfallCollectionLayout")]
public class WaterfallCollectionLayout : UICollectionViewLayout
{
#region Private Variables
private int columnCount = 2;
private nfloat minimumColumnSpacing = 10;
private nfloat minimumInterItemSpacing = 10;
private nfloat headerHeight = 0.0f;
private nfloat footerHeight = 0.0f;
private UIEdgeInsets sectionInset = new UIEdgeInsets(0, 0, 0, 0);
private WaterfallCollectionRenderDirection itemRenderDirection = WaterfallCollectionRenderDirection.ShortestFirst;
private Dictionary<nint,UICollectionViewLayoutAttributes> headersAttributes = new Dictionary<nint, UICollectionViewLayoutAttributes>();
private Dictionary<nint,UICollectionViewLayoutAttributes> footersAttributes = new Dictionary<nint, UICollectionViewLayoutAttributes>();
private List<CGRect> unionRects = new List<CGRect>();
private List<nfloat> columnHeights = new List<nfloat>();
private List<UICollectionViewLayoutAttributes> allItemAttributes = new List<UICollectionViewLayoutAttributes>();
private List<List<UICollectionViewLayoutAttributes>> sectionItemAttributes = new List<List<UICollectionViewLayoutAttributes>>();
private nfloat unionSize = 20;
#endregion
#region Computed Properties
[Export("ColumnCount")]
public int ColumnCount {
get { return columnCount; }
set {
WillChangeValue ("ColumnCount");
columnCount = value;
DidChangeValue ("ColumnCount");
InvalidateLayout ();
}
}
[Export("MinimumColumnSpacing")]
public nfloat MinimumColumnSpacing {
get { return minimumColumnSpacing; }
set {
WillChangeValue ("MinimumColumnSpacing");
minimumColumnSpacing = value;
DidChangeValue ("MinimumColumnSpacing");
InvalidateLayout ();
}
}
[Export("MinimumInterItemSpacing")]
public nfloat MinimumInterItemSpacing {
get { return minimumInterItemSpacing; }
set {
WillChangeValue ("MinimumInterItemSpacing");
minimumInterItemSpacing = value;
DidChangeValue ("MinimumInterItemSpacing");
InvalidateLayout ();
}
}
[Export("HeaderHeight")]
public nfloat HeaderHeight {
get { return headerHeight; }
set {
WillChangeValue ("HeaderHeight");
headerHeight = value;
DidChangeValue ("HeaderHeight");
InvalidateLayout ();
}
}
[Export("FooterHeight")]
public nfloat FooterHeight {
get { return footerHeight; }
set {
WillChangeValue ("FooterHeight");
footerHeight = value;
DidChangeValue ("FooterHeight");
InvalidateLayout ();
}
}
[Export("SectionInset")]
public UIEdgeInsets SectionInset {
get { return sectionInset; }
set {
WillChangeValue ("SectionInset");
sectionInset = value;
DidChangeValue ("SectionInset");
InvalidateLayout ();
}
}
[Export("ItemRenderDirection")]
public WaterfallCollectionRenderDirection ItemRenderDirection {
get { return itemRenderDirection; }
set {
WillChangeValue ("ItemRenderDirection");
itemRenderDirection = value;
DidChangeValue ("ItemRenderDirection");
InvalidateLayout ();
}
}
#endregion
#region Constructors
public WaterfallCollectionLayout ()
{
}
public WaterfallCollectionLayout(NSCoder coder) : base(coder) {
}
#endregion
#region Public Methods
public nfloat ItemWidthInSectionAtIndex(int section) {
var width = CollectionView.Bounds.Width - SectionInset.Left - SectionInset.Right;
return (nfloat)Math.Floor ((width - ((ColumnCount - 1) * MinimumColumnSpacing)) / ColumnCount);
}
#endregion
#region Override Methods
public override void PrepareLayout ()
{
base.PrepareLayout ();
// Get the number of sections
var numberofSections = CollectionView.NumberOfSections();
if (numberofSections == 0)
return;
// Reset collections
headersAttributes.Clear ();
footersAttributes.Clear ();
unionRects.Clear ();
columnHeights.Clear ();
allItemAttributes.Clear ();
sectionItemAttributes.Clear ();
// Initialize column heights
for (int n = 0; n < ColumnCount; n++) {
columnHeights.Add ((nfloat)0);
}
// Process all sections
nfloat top = 0.0f;
var attributes = new UICollectionViewLayoutAttributes ();
var columnIndex = 0;
for (nint section = 0; section < numberofSections; ++section) {
// Calculate section specific metrics
var minimumInterItemSpacing = (MinimumInterItemSpacingForSection == null) ? MinimumColumnSpacing :
MinimumInterItemSpacingForSection (CollectionView, this, section);
// Calculate widths
var width = CollectionView.Bounds.Width - SectionInset.Left - SectionInset.Right;
var itemWidth = (nfloat)Math.Floor ((width - ((ColumnCount - 1) * MinimumColumnSpacing)) / ColumnCount);
// Calculate section header
var heightHeader = (HeightForHeader == null) ? HeaderHeight :
HeightForHeader (CollectionView, this, section);
if (heightHeader > 0) {
attributes = UICollectionViewLayoutAttributes.CreateForSupplementaryView (UICollectionElementKindSection.Header, NSIndexPath.FromRowSection (0, section));
attributes.Frame = new CGRect (0, top, CollectionView.Bounds.Width, heightHeader);
headersAttributes.Add (section, attributes);
allItemAttributes.Add (attributes);
top = attributes.Frame.GetMaxY ();
}
top += SectionInset.Top;
for (int n = 0; n < ColumnCount; n++) {
columnHeights [n] = top;
}
// Calculate Section Items
var itemCount = CollectionView.NumberOfItemsInSection(section);
List<UICollectionViewLayoutAttributes> itemAttributes = new List<UICollectionViewLayoutAttributes> ();
for (nint n = 0; n < itemCount; n++) {
var indexPath = NSIndexPath.FromRowSection (n, section);
columnIndex = NextColumnIndexForItem (n);
var xOffset = SectionInset.Left + (itemWidth + MinimumColumnSpacing) * (nfloat)columnIndex;
var yOffset = columnHeights [columnIndex];
var itemSize = (SizeForItem == null) ? new CGSize (0, 0) : SizeForItem (CollectionView, this, indexPath);
nfloat itemHeight = 0.0f;
if (itemSize.Height > 0.0f && itemSize.Width > 0.0f) {
itemHeight = (nfloat)Math.Floor (itemSize.Height * itemWidth / itemSize.Width);
}
attributes = UICollectionViewLayoutAttributes.CreateForCell (indexPath);
attributes.Frame = new CGRect (xOffset, yOffset, itemWidth, itemHeight);
itemAttributes.Add (attributes);
allItemAttributes.Add (attributes);
columnHeights [columnIndex] = attributes.Frame.GetMaxY () + MinimumInterItemSpacing;
}
sectionItemAttributes.Add (itemAttributes);
// Calculate Section Footer
nfloat footerHeight = 0.0f;
columnIndex = LongestColumnIndex();
top = columnHeights [columnIndex] - MinimumInterItemSpacing + SectionInset.Bottom;
footerHeight = (HeightForFooter == null) ? FooterHeight : HeightForFooter(CollectionView, this, section);
if (footerHeight > 0) {
attributes = UICollectionViewLayoutAttributes.CreateForSupplementaryView (UICollectionElementKindSection.Footer, NSIndexPath.FromRowSection (0, section));
attributes.Frame = new CGRect (0, top, CollectionView.Bounds.Width, footerHeight);
footersAttributes.Add (section, attributes);
allItemAttributes.Add (attributes);
top = attributes.Frame.GetMaxY ();
}
for (int n = 0; n < ColumnCount; n++) {
columnHeights [n] = top;
}
}
var i =0;
var attrs = allItemAttributes.Count;
while(i < attrs) {
var rect1 = allItemAttributes [i].Frame;
i = (int)Math.Min (i + unionSize, attrs) - 1;
var rect2 = allItemAttributes [i].Frame;
unionRects.Add (CGRect.Union (rect1, rect2));
i++;
}
}
public override CGSize CollectionViewContentSize {
get {
if (CollectionView.NumberOfSections () == 0) {
return new CGSize (0, 0);
}
var contentSize = CollectionView.Bounds.Size;
contentSize.Height = columnHeights [0];
return contentSize;
}
}
public override UICollectionViewLayoutAttributes LayoutAttributesForItem (NSIndexPath indexPath)
{
if (indexPath.Section >= sectionItemAttributes.Count) {
return null;
}
if (indexPath.Item >= sectionItemAttributes [indexPath.Section].Count) {
return null;
}
var list = sectionItemAttributes [indexPath.Section];
return list [(int)indexPath.Item];
}
public override UICollectionViewLayoutAttributes LayoutAttributesForSupplementaryView (NSString kind, NSIndexPath indexPath)
{
var attributes = new UICollectionViewLayoutAttributes ();
switch (kind) {
case "header":
attributes = headersAttributes [indexPath.Section];
break;
case "footer":
attributes = footersAttributes [indexPath.Section];
break;
}
return attributes;
}
public override UICollectionViewLayoutAttributes[] LayoutAttributesForElementsInRect (CGRect rect)
{
var begin = 0;
var end = unionRects.Count;
List<UICollectionViewLayoutAttributes> attrs = new List<UICollectionViewLayoutAttributes> ();
for (int i = 0; i < end; i++) {
if (rect.IntersectsWith(unionRects[i])) {
begin = i * (int)unionSize;
}
}
for (int i = end - 1; i >= 0; i--) {
if (rect.IntersectsWith (unionRects [i])) {
end = (int)Math.Min ((i + 1) * (int)unionSize, allItemAttributes.Count);
break;
}
}
for (int i = begin; i < end; i++) {
var attr = allItemAttributes [i];
if (rect.IntersectsWith (attr.Frame)) {
attrs.Add (attr);
}
}
return attrs.ToArray();
}
public override bool ShouldInvalidateLayoutForBoundsChange (CGRect newBounds)
{
var oldBounds = CollectionView.Bounds;
return (newBounds.Width != oldBounds.Width);
}
#endregion
#region Private Methods
private int ShortestColumnIndex() {
var index = 0;
var shortestHeight = nfloat.MaxValue;
var n = 0;
// Scan each column for the shortest height
foreach (nfloat height in columnHeights) {
if (height < shortestHeight) {
shortestHeight = height;
index = n;
}
++n;
}
return index;
}
private int LongestColumnIndex() {
var index = 0;
var longestHeight = nfloat.MinValue;
var n = 0;
// Scan each column for the shortest height
foreach (nfloat height in columnHeights) {
if (height > longestHeight) {
longestHeight = height;
index = n;
}
++n;
}
return index;
}
private int NextColumnIndexForItem(nint item) {
var index = 0;
switch (ItemRenderDirection) {
case WaterfallCollectionRenderDirection.ShortestFirst:
index = ShortestColumnIndex ();
break;
case WaterfallCollectionRenderDirection.LeftToRight:
index = ColumnCount;
break;
case WaterfallCollectionRenderDirection.RightToLeft:
index = (ColumnCount - 1) - ((int)item / ColumnCount);
break;
}
return index;
}
#endregion
#region Events
public delegate CGSize WaterfallCollectionSizeDelegate(UICollectionView collectionView, WaterfallCollectionLayout layout, NSIndexPath indexPath);
public delegate nfloat WaterfallCollectionFloatDelegate(UICollectionView collectionView, WaterfallCollectionLayout layout, nint section);
public delegate UIEdgeInsets WaterfallCollectionEdgeInsetsDelegate(UICollectionView collectionView, WaterfallCollectionLayout layout, nint section);
public event WaterfallCollectionSizeDelegate SizeForItem;
public event WaterfallCollectionFloatDelegate HeightForHeader;
public event WaterfallCollectionFloatDelegate HeightForFooter;
public event WaterfallCollectionEdgeInsetsDelegate InsetForSection;
public event WaterfallCollectionFloatDelegate MinimumInterItemSpacingForSection;
#endregion
}
}
Dies kann eine Klasse verwendet werden, um der Sammlungsansicht ein benutzerdefiniertes Zweispaltenlayout vom Wasserfalltyp bereitzustellen.
Der Code verwendet Key-Value Coding (über die WillChangeValue
und DidChangeValue
Methoden), um datenbindung für unsere berechneten Eigenschaften in dieser Klasse bereitzustellen.
Bearbeiten Sie als Nächstes die WaterfallCollectionSource
folgenden Änderungen und Ergänzungen, und nehmen Sie sie vor:
private Random rnd = new Random();
...
public List<nfloat> Heights { get; set; } = new List<nfloat> ();
...
public WaterfallCollectionSource (WaterfallCollectionView collectionView)
{
// Initialize
CollectionView = collectionView;
// Init numbers collection
for (int n = 0; n < 100; ++n) {
Numbers.Add (n);
Heights.Add (rnd.Next (0, 100) + 40.0f);
}
}
Dadurch wird für jedes element, das in der Liste angezeigt wird, eine zufällige Höhe erstellt.
Bearbeiten Sie als Nächstes die WaterfallCollectionView
Klasse, und fügen Sie die folgende Hilfseigenschaft hinzu:
public WaterfallCollectionSource Source {
get { return (WaterfallCollectionSource)DataSource; }
}
Dies erleichtert das Abrufen der Datenquelle (und der Elementhöhen) aus dem benutzerdefinierten Layout.
Bearbeiten Sie schließlich den Ansichtscontroller, und fügen Sie den folgenden Code hinzu:
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
var waterfallLayout = new WaterfallCollectionLayout ();
// Wireup events
waterfallLayout.SizeForItem += (collectionView, layout, indexPath) => {
var collection = collectionView as WaterfallCollectionView;
return new CGSize((View.Bounds.Width-40)/3,collection.Source.Heights[(int)indexPath.Item]);
};
// Attach the custom layout to the collection
CollectionView.SetCollectionViewLayout(waterfallLayout, false);
}
Dadurch wird eine Instanz unseres benutzerdefinierten Layouts erstellt, das Ereignis festgelegt, um die Größe jedes Elements bereitzustellen und das neue Layout an unsere Sammlungsansicht anzufügen.
Wenn wir die Xamarin.iOS-App erneut ausführen, sieht die Sammlungsansicht nun wie folgt aus:
Wir können Elemente nach wie vor ziehen und neu anordnen, aber die Elemente ändern jetzt die Größe an ihre neue Position, wenn sie gelöscht werden.
Änderungen der Sammlungsansicht
In den folgenden Abschnitten befassen wir uns ausführlich mit den Änderungen, die an den einzelnen Klassen in der Sammlungsansicht von iOS 9 vorgenommen wurden.
UICollectionView
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionView
Klasse für iOS 9 vorgenommen:
BeginInteractiveMovementForItem
– Markiert den Anfang eines Ziehvorgangs.CancelInteractiveMovement
– Informiert die Sammlungsansicht, dass der Benutzer einen Ziehvorgang abgebrochen hat.EndInteractiveMovement
– Informiert die Sammlungsansicht, dass der Benutzer einen Ziehvorgang abgeschlossen hat.GetIndexPathsForVisibleSupplementaryElements
– Gibt dieindexPath
Kopf- oder Fußzeile in einem Sammlungsansichtsbereich zurück.GetSupplementaryView
– Gibt die angegebene Kopf- oder Fußzeile zurück.GetVisibleSupplementaryViews
– Gibt eine Liste aller sichtbaren Kopf- und Fußzeilen zurück.UpdateInteractiveMovementTargetPosition
– Informiert die Sammlungsansicht, dass der Benutzer während eines Ziehvorgangs ein Element verschoben oder verschoben hat.
UICollectionViewController
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionViewController
Klasse in iOS 9 vorgenommen:
InstallsStandardGestureForInteractiveMovement
– Wenntrue
die neue Gestenerkennung, die automatisch drag-to-reorder unterstützt, verwendet wird.CanMoveItem
– Informiert die Sammlungsansicht, wenn ein bestimmtes Element neu angeordnet werden kann.GetTargetContentOffset
– Wird verwendet, um den Offset eines bestimmten Sammlungsansichtselements abzurufen.GetTargetIndexPathForMove
– Ruft dasindexPath
element eines bestimmten Elements für einen Ziehvorgang ab.MoveItem
– Verschiebt die Reihenfolge eines bestimmten Elements in der Liste.
UICollectionViewDataSource
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionViewDataSource
Klasse in iOS 9 vorgenommen:
CanMoveItem
– Informiert die Sammlungsansicht, wenn ein bestimmtes Element neu angeordnet werden kann.MoveItem
– Verschiebt die Reihenfolge eines bestimmten Elements in der Liste.
UICollectionViewDelegate
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionViewDelegate
Klasse in iOS 9 vorgenommen:
GetTargetContentOffset
– Wird verwendet, um den Offset eines bestimmten Sammlungsansichtselements abzurufen.GetTargetIndexPathForMove
– Ruft dasindexPath
element eines bestimmten Elements für einen Ziehvorgang ab.
UICollectionViewFlowLayout
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionViewFlowLayout
Klasse in iOS 9 vorgenommen:
SectionFootersPinToVisibleBounds
– Hält die Abschnittsfußzeilen an die Grenzen der sichtbaren Sammlungsansicht fest.SectionHeadersPinToVisibleBounds
– Übergibt die Abschnittsüberschriften an die Grenzen der sichtbaren Sammlungsansicht.
UICollectionViewLayout
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionViewLayout
Klasse in iOS 9 vorgenommen:
GetInvalidationContextForEndingInteractiveMovementOfItems
– Gibt den Ungültigkeitskontext am Ende eines Ziehvorgangs zurück, wenn der Benutzer den Ziehvorgang beendet oder abbricht.GetInvalidationContextForInteractivelyMovingItems
– Gibt den Ungültigkeitskontext am Anfang eines Ziehvorgangs zurück.GetLayoutAttributesForInteractivelyMovingItem
– Ruft die Layoutattribute für ein bestimmtes Element beim Ziehen eines Elements ab.GetTargetIndexPathForInteractivelyMovingItem
– Gibt dasindexPath
Element zurück, das sich beim Ziehen eines Elements am angegebenen Punkt befindet.
UICollectionViewLayoutAttributes
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionViewLayoutAttributes
Klasse in iOS 9 vorgenommen:
CollisionBoundingPath
– Gibt den Kollisionspfad zweier Elemente während eines Ziehvorgangs zurück.CollisionBoundsType
– Gibt den Typ der Kollision (als aUIDynamicItemCollisionBoundsType
) zurück, die während eines Ziehvorgangs aufgetreten ist.
UICollectionViewLayoutInvalidationContext
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionViewLayoutInvalidationContext
Klasse in iOS 9 vorgenommen:
InteractiveMovementTarget
– Gibt das Zielelement eines Ziehvorgangs zurück.PreviousIndexPathsForInteractivelyMovingItems
– Gibt die anderen Elemente zurück, dieindexPaths
an einer Ziehaktion beteiligt sind, um den Vorgang neu anzuordnen.TargetIndexPathsForInteractivelyMovingItems
– Gibt die Elemente zurück, dieindexPaths
aufgrund eines Vorgangs zum Neuanordnen des Ziehens neu angeordnet werden.
UICollectionViewSource
Die folgenden Änderungen oder Ergänzungen wurden an der UICollectionViewSource
Klasse in iOS 9 vorgenommen:
CanMoveItem
– Informiert die Sammlungsansicht, wenn ein bestimmtes Element neu angeordnet werden kann.GetTargetContentOffset
– Gibt die Offsets von Elementen zurück, die über einen Drag-to-Reorder-Vorgang verschoben werden.GetTargetIndexPathForMove
– Gibt dasindexPath
Element zurück, das während eines Vorgangs zum Neuanordnen verschoben wird.MoveItem
– Verschiebt die Reihenfolge eines bestimmten Elements in der Liste.
Zusammenfassung
In diesem Artikel wurden die Änderungen an Sammlungsansichten in iOS 9 behandelt und beschrieben, wie sie in Xamarin.iOS implementiert werden. Die Implementierung einer einfachen Aktion zum Neuanordnen von Drag-to-Reorder in einer Sammlungsansicht wurde behandelt. Verwenden einer benutzerdefinierten Gestenerkennung mit drag-to-reorder; und wie sich drag-to-reorder auf ein benutzerdefiniertes Sammlungsansichtslayout auswirkt.