Einheitliche Storyboards in Xamarin.iOS

iOS 8 enthält einen neuen, einfacher zu verwendenden Mechanismus zum Erstellen der Benutzeroberfläche – das einheitliche Storyboard. Mit einem einzelnen Storyboard, um alle verschiedenen Hardwarebildschirmgrößen abzudecken, können schnelle und reaktionsfähige Ansichten im Stil "Design-once, use-many" erstellt werden.

Da der Entwickler kein separates und spezifisches Storyboard mehr für iPhone- und iPad-Geräte erstellen muss, hat er die Flexibilität, Anwendungen mit einer gemeinsamen Benutzeroberfläche zu entwerfen und diese Schnittstelle dann für verschiedene Größenklassen anzupassen. Auf diese Weise kann eine Anwendung an die Stärken jedes Formfaktors angepasst und jede Benutzeroberfläche optimiert werden, um die beste Benutzeroberfläche zu bieten.

Größenklassen

Vor iOS 8 hat der Entwickler zwischen Hoch- und UIInterfaceIdiom Querformat sowie zwischen iPhone- und iPad-Geräten unterschiedenUIInterfaceOrientation. In iOS8 wird die Ausrichtung und das Gerät mithilfe von Größenklassen bestimmt.

Geräte werden durch Größenklassen sowohl in vertikalen als auch in horizontalen Achsen definiert, und es gibt zwei Arten von Größenklassen in iOS 8:

  • Normal – Dies ist entweder für eine große Bildschirmgröße (z. B. ein iPad) oder ein Gadget, das den Eindruck einer großen Größe vermittelt (z. B. UIScrollView
  • Kompakt : Dies gilt für kleinere Geräte (z. B. ein iPhone). Diese Größe berücksichtigt die Ausrichtung des Geräts.

Wenn die beiden Konzepte zusammen verwendet werden, ist das Ergebnis ein Raster von 2 x 2, das die verschiedenen möglichen Größen definiert, die in den beiden unterschiedlichen Ausrichtungen verwendet werden können, wie im folgenden Diagramm dargestellt:

Ein Raster von 2 x 2, das die verschiedenen möglichen Größen definiert, die in regulärer und kompakter Ausrichtung verwendet werden können

Der Entwickler kann einen Ansichtscontroller erstellen, der eine der vier Möglichkeiten verwendet, die zu unterschiedlichen Layouts führen würden (wie in den obigen Grafiken zu sehen).

iPad-Größenklassen

Das iPad verfügt aufgrund der Größe über eine reguläre Klassengröße für beide Ausrichtungen.

iPad-Größenklassen

iPhone-Größenklassen

Das iPhone hat je nach Ausrichtung des Geräts unterschiedliche Größenklassen:

iPhone-Größenklassen

  • Wenn sich das Gerät im Hochformatmodus befindet, verfügt der Bildschirm über eine kompakten Klasse horizontal und regelmäßig vertikal.
  • Wenn sich das Gerät im Querformatmodus befindet, werden die Bildschirmklassen vom Hochformatmodus umgekehrt.

iPhone 6 Plus Größenklassen

Die Größen entsprechen den früheren iPhones im Hochformat, unterscheiden sich jedoch im Querformat:

iPhone 6 Plus Größenklassen

Da das iPhone 6 Plus über einen ausreichend großen Bildschirm verfügt, ist es in der Lage, im Querformatmodus eine Klasse der regulären Breite zu haben.

Unterstützung für eine neue Bildschirmskalierung

Das iPhone 6 Plus verwendet ein neues Retina HD-Display mit einem Bildschirmskalierungsfaktor von 3,0 (dreimal so groß wie die ursprüngliche iPhone-Bildschirmauflösung). Um die bestmögliche Benutzererfahrung auf diesen Geräten zu bieten, fügen Sie neue Grafiken ein, die für diese Bildschirmskala entworfen wurden. In Xcode 6 und höher können Objektkataloge Bilder mit den Größen 1x, 2x und 3x enthalten. Fügen Sie einfach die neuen Imageressourcen hinzu, und iOS wählt die richtigen Ressourcen aus, wenn sie auf einem iPhone 6 Plus ausgeführt werden.

Das Bildladeverhalten in iOS erkennt auch ein @3x Suffix für Bilddateien. Wenn der Entwickler beispielsweise ein Imageobjekt (mit unterschiedlichen Auflösungen) in das Paket der Anwendung mit den folgenden Dateinamen einschließt: MonkeyIcon.png, MonkeyIcon@2x.pngund MonkeyIcon@3x.png. Auf dem iPhone 6 Plus wird das MonkeyIcon@3x.png Image automatisch verwendet, wenn der Entwickler ein Bild mit dem folgenden Code lädt:

UIImage icon = UIImage.FromFile("MonkeyImage.png");

Dynamische Startbildschirme

Die Startbildschirmdatei wird als Begrüßungsbildschirm angezeigt, während eine iOS-Anwendung gestartet wird, um dem Benutzer Feedback zu geben, dass die App tatsächlich gestartet wird. Vor iOS 8 musste der Entwickler mehrere Default.png Bildressourcen für jeden Gerätetyp, jede Ausrichtung und bildschirmauflösung einschließen, auf der die Anwendung ausgeführt wird.

Neu bei iOS 8 kann der Entwickler eine einzelne, atomare .xib Datei in Xcode erstellen, die autolayout- und größenklassen verwendet, um einen dynamischen Startbildschirm zu erstellen, der für jedes Gerät, jede Auflösung und ausrichtung funktioniert. Dies reduziert nicht nur den Aufwand des Entwicklers, um alle erforderlichen Imageressourcen zu erstellen und zu verwalten, sondern auch die Größe des installierten Pakets der Anwendung.

Merkmale

Merkmale sind Eigenschaften, die verwendet werden können, um zu bestimmen, wie sich ein Layout ändert, wenn sich seine Umgebung ändert. Sie bestehen aus einer Reihe von Eigenschaften (die HorizontalSizeClass und VerticalSizeClass basierend auf UIUserInterfaceSizeClass), sowie der Schnittstellensprache ( UIUserInterfaceIdiom) und der Anzeigeskala.

Alle oben genannten Zustände werden in einem Container eingeschlossen, den Apple als Trait Collection ( UITraitCollection) bezeichnet, der nicht nur die Eigenschaften, sondern auch deren Werte enthält.

Eigenschaftsumgebung

Trait Environments sind eine neue Schnittstelle in iOS 8 und können eine Trait-Auflistung für die folgenden Objekte zurückgeben:

  • Bildschirme ( UIScreens ).
  • Windows ( UIWindows ).
  • Controller anzeigen ( UIViewController ).
  • Ansichten ( UIView ).
  • Präsentationscontroller ( UIPresentationController ).

Der Entwickler verwendet die trait Collection, die von einer Trait-Umgebung zurückgegeben wird, um zu bestimmen, wie eine Benutzeroberfläche gestaltet werden soll.

Alle Trait-Umgebungen bilden eine Hierarchie, wie im folgenden Diagramm dargestellt:

Hierarchiediagramm für Trait-Umgebungen

Die Trait-Auflistung, über die jede der oben genannten Trait-Umgebungen verfügt, wird standardmäßig vom übergeordneten Element zur untergeordneten Umgebung übertragen.

Zusätzlich zum Abrufen der aktuellen Trait-Auflistung verfügt die Trait-Umgebung über eine TraitCollectionDidChange Methode, die in den Unterklassen View oder View Controller überschrieben werden kann. Der Entwickler kann diese Methode verwenden, um alle UI-Elemente zu ändern, die von Merkmalen abhängig sind, wenn sich diese Merkmale geändert haben.

Typische Traitsammlungen

In diesem Abschnitt werden die typischen Arten von Traitsammlungen behandelt, die dem Benutzer bei der Arbeit mit iOS 8 auftreten.

Im Folgenden sehen Sie eine typische Trait-Sammlung, die dem Entwickler möglicherweise auf einem iPhone angezeigt wird:

Eigenschaft Wert
HorizontalSizeClass Kompakt
VerticalSizeClass Regulär
UserInterfaceIdom Phone
DisplayScale 2.0

Der obige Satz würde eine vollqualifizierte Trait-Sammlung darstellen, da sie Werte für alle ihre Eigenschaftseigenschaften aufweist.

Es ist auch möglich, eine Trait Collection zu haben, die einige ihrer Werte fehlt (die Apple als Nicht angegeben bezeichnet):

Eigenschaft Wert
HorizontalSizeClass Kompakt
VerticalSizeClass Nicht angegeben.
UserInterfaceIdom Nicht angegeben.
DisplayScale Nicht angegeben.

Wenn der Entwickler die Trait-Umgebung jedoch nach seiner Trait-Sammlung fragt, gibt er eine vollqualifizierte Sammlung zurück, wie im obigen Beispiel gezeigt.

Wenn sich eine Trait-Umgebung (z. B. eine Ansicht oder ein Ansichtscontroller) nicht innerhalb der aktuellen Ansichtshierarchie befindet, erhält der Entwickler möglicherweise nicht angegebene Werte für eine oder mehrere der Eigenschaftseigenschaften zurück.

Der Entwickler erhält auch eine teilweise qualifizierte Trait Collection, wenn er eine der von Apple bereitgestellten Erstellungsmethoden verwendet, z UITraitCollection.FromHorizontalSizeClass. B. , um eine neue Sammlung zu erstellen.

Ein Vorgang, der für mehrere Trait-Sammlungen ausgeführt werden kann, besteht darin, diese miteinander zu vergleichen, wobei eine Trait-Sammlung gefragt wird, ob sie eine andere enthält. Mit Containment ist gemeint, dass für alle in der zweiten Auflistung angegebenen Eigenschaften der Wert genau mit dem Wert in der ersten Auflistung übereinstimmen muss.

Um zwei Merkmale zu testen, verwenden Sie die Contains Methode der UITraitCollection Übergabe des Werts des zu testenden Merkmals.

Der Entwickler kann die Vergleiche manuell im Code durchführen, um zu bestimmen, wie Ansichten oder Ansichtscontroller zu layouten sind. Verwendet diese Methode jedoch intern, UIKit um einige ihrer Funktionen bereitzustellen, z. B. im Darstellungsproxy.

Darstellungsproxy

Der Darstellungsproxy wurde in früheren Versionen von iOS eingeführt, damit Entwickler die Eigenschaften ihrer Ansichten anpassen können. Es wurde in iOS 8 erweitert, um Trait Collections zu unterstützen.

Appearance Proxys enthalten jetzt eine neue Methode, AppearanceForTraitCollection, die einen neuen Darstellungsproxy für die angegebene Trait-Auflistung zurückgibt, die übergeben wurde. Alle Anpassungen, die der Entwickler für diesen Darstellungsproxy ausführt, werden nur für Ansichten wirksam, die der angegebenen Trait-Sammlung entsprechen.

Im Allgemeinen übergibt der Entwickler eine teilweise angegebene Trait-Sammlung an die -Methode, z. B. eine, die AppearanceForTraitCollection gerade eine horizontale Größenklasse von Compact angegeben hat, sodass er jede Ansicht in der Anwendung anpassen kann, die horizontal kompakt ist.

UIImage

Eine weitere Klasse, zu der Apple Trait Collection hinzugefügt hat, ist UIImage. In der Vergangenheit musste der Entwickler eine @1X und @2x Version jedes Bitmapgrafikobjekts angeben, das er in die Anwendung aufnehmen sollte (z. B. ein Symbol).

iOS 8 wurde erweitert, damit entwickler basierend auf einer Trait-Sammlung mehrere Versionen eines Images in einen Imagekatalog aufnehmen können. Der Entwickler könnte beispielsweise ein kleineres Image für die Arbeit mit einer Kompakt-Trait-Klasse und ein Bild in voller Größe für jede andere Sammlung einschließen.

Wenn eines der Bilder in einer UIImageView Klasse verwendet wird, zeigt die Bildansicht automatisch die richtige Version des Bilds für die Trait-Sammlung an. Wenn sich die Trait-Umgebung ändert (z. B. wenn der Benutzer das Gerät vom Hochformat ins Querformat wechselt), wählt die Bildansicht automatisch die neue Bildgröße aus, um der neuen Trait-Sammlung zu entsprechen, und ändert die Größe so, dass sie der aktuellen Version des angezeigten Bilds entspricht.

UIImageAsset

Apple hat iOS 8 eine neue Klasse mit dem Namen UIImageAsset hinzugefügt, um dem Entwickler noch mehr Kontrolle über die Bildauswahl zu geben.

Ein Image-Asset schließt alle verschiedenen Versionen eines Images ab und ermöglicht es dem Entwickler, nach einem bestimmten Bild zu fragen, das einer trait Collection entspricht, die übergeben wurde. Bilder können on-the-fly hinzugefügt oder daraus entfernt werden.

Weitere Informationen zu Imageressourcen finden Sie in der Dokumentation zu UiImageAsset von Apple.

Kombinieren von Trait-Sammlungen

Eine weitere Funktion, die ein Entwickler für Trait-Sammlungen ausführen kann, ist das Hinzufügen von zwei zusammen, was zu der kombinierten Auflistung führt, bei der die nicht angegebenen Werte aus einer Auflistung durch die angegebenen Werte in einer zweiten Sammlung ersetzt werden. Dies geschieht mit der FromTraitsFromCollections -Methode der UITraitCollection -Klasse.

Wie oben erwähnt, wird der Wert auf die angegebene Version festgelegt, wenn eines der Merkmale in einer der Trait-Sammlungen nicht angegeben und in einer anderen angegeben wird. Wenn jedoch mehrere Versionen eines bestimmten Werts angegeben sind, ist der Wert aus der letzten Trait-Sammlung der wert, der verwendet wird.

Controller für adaptive Ansicht

In diesem Abschnitt erfahren Sie, wie die iOS-Ansichts- und Ansichtscontroller die Konzepte von Merkmalen und Größenklassen übernommen haben, um automatisch anpassungsfähiger in den Anwendungen des Entwicklers zu sein.

Controller für geteilte Ansicht

Eine der View Controller-Klassen, die sich in iOS 8 am meisten geändert hat, ist die UISplitViewController -Klasse. In der Vergangenheit hat der Entwickler häufig einen Split View Controller auf der iPad-Version der Anwendung verwendet und dann eine völlig andere Version seiner Ansichtshierarchie für die iPhone-Version der App bereitstellen müssen.

In iOS 8 ist die UISplitViewController Klasse auf beiden Plattformen (iPad und iPhone) verfügbar, wodurch der Entwickler eine View Controller-Hierarchie erstellen kann, die sowohl für iPhone als auch für iPad funktioniert.

Wenn sich ein iPhone im Querformat befindet, zeigt der Split View Controller seine Ansichten nebeneinander an, genau wie bei der Anzeige auf einem iPad.

Überschreiben von Merkmalen

Trait Environments kaskadieren vom übergeordneten Container auf die untergeordneten Container, wie in der folgenden Grafik, die einen Split View Controller auf einem iPad im Querformat zeigt:

Ein Split View Controller auf einem iPad im Querformat

Da das iPad sowohl horizontal als auch vertikal über eine Reguläre Größenklasse verfügt, zeigt die geteilte Ansicht sowohl die master- als auch die Detailansicht an.

Auf einem iPhone, bei dem die Größenklasse in beiden Ausrichtungen kompakt ist, zeigt der Split View Controller nur die Detailansicht an, wie unten dargestellt:

Der Controller für geteilte Ansicht zeigt nur die Detailansicht an.

In einer Anwendung, in der der Entwickler sowohl die master- als auch die Detailansicht auf einem iPhone im Querformat anzeigen möchte, muss der Entwickler einen übergeordneten Container für den Split View Controller einfügen und die Trait-Sammlung überschreiben. Wie in der folgenden Grafik dargestellt:

Der Entwickler muss einen übergeordneten Container für den Split View Controller einfügen und die Trait-Sammlung außer Kraft setzen.

Ein UIView wird als übergeordnetes Element des Split View Controller festgelegt, und die -Methode wird aufgerufen, wenn die SetOverrideTraitCollection Ansicht eine neue Trait-Sammlung übergeben und auf den Split View Controller ausgerichtet ist. Die neue Trait-Sammlung setzt die HorizontalSizeClasseinstellung auf Regularaußer Kraft, sodass der Split View Controller sowohl die master- als auch die Detailansichten auf einem iPhone im Querformat anzeigt.

Beachten Sie, dass auf VerticalSizeClass festgelegt unspecifiedwurde, wodurch die neue Trait-Sammlung der Trait-Auflistung auf dem übergeordneten Element hinzugefügt werden kann, was zu einem Compact VerticalSizeClass für den untergeordneten Split View Controller führt.

Trait-Änderungen

In diesem Abschnitt wird ausführlich erläutert, wie die Trait-Sammlungen bei Änderungen der Trait-Umgebung übergehen. Beispielsweise, wenn das Gerät vom Hochformat ins Querformat gedreht wird.

Übersicht über Die Änderungen von Merkmalen im Hoch- in querformat

Zunächst führt iOS 8 einige Setups durch, um den Übergang vorzubereiten. Als Nächstes animiert das System den Übergangszustand. Schließlich bereinigt iOS 8 alle temporären Zustände, die während des Übergangs erforderlich sind.

iOS 8 bietet mehrere Rückrufe, die der Entwickler verwenden kann, um an der Trait-Änderung teilzunehmen, wie in der folgenden Tabelle dargestellt:

Phase Rückruf BESCHREIBUNG
Setup
  • WillTransitionToTraitCollection
  • TraitCollectionDidChange
  • Diese Methode wird am Anfang einer Trait-Änderung aufgerufen, bevor eine Trait-Auflistung auf ihren neuen Wert festgelegt wird.
  • Die -Methode wird aufgerufen, wenn sich der Wert der Trait-Auflistung geändert hat, aber bevor eine Animation stattfindet.
Animation WillTransitionToTraitCollection Der Übergangskoordinator, der an diese Methode übergeben wird, verfügt über eine AnimateAlongside Eigenschaft, die es dem Entwickler ermöglicht, Animationen hinzuzufügen, die zusammen mit den Standardanimationen ausgeführt werden.
Bereinigung WillTransitionToTraitCollection Stellt eine Methode bereit, mit der Entwickler nach dem Übergang ihren eigenen Bereinigungscode einschließen können.

Die WillTransitionToTraitCollection -Methode eignet sich hervorragend zum Animieren von Ansichtscontrollern zusammen mit den Trait Collection-Änderungen. Die WillTransitionToTraitCollection -Methode ist nur für Ansichtscontroller ( UIViewController) und nicht für andere Trait-Umgebungen wie UIViewsverfügbar.

Eignet TraitCollectionDidChange sich hervorragend für die Arbeit mit der UIView -Klasse, in der der Entwickler die Benutzeroberfläche aktualisieren möchte, wenn sich die Merkmale ändern.

Reduzieren der Geteilten Ansichtscontroller

Sehen wir uns nun genauer an, was passiert, wenn ein Split View Controller von einer zwei Spalte in eine Spaltenansicht reduziert wird. Im Rahmen dieser Änderung müssen zwei Prozesse auftreten:

  • Standardmäßig verwendet der Split View Controller den primären Ansichtscontroller als Ansicht nach dem Reduzieren. Der Entwickler kann dieses Verhalten überschreiben, indem er die GetPrimaryViewControllerForCollapsingSplitViewController Methode von UISplitViewControllerDelegate überschreibt und alle View Controller bereitstellt, die im reduzierten Zustand angezeigt werden sollen.
  • Der sekundäre Ansichtscontroller muss mit dem primären Ansichtscontroller zusammengeführt werden. In der Regel muss der Entwickler keine Maßnahmen für diesen Schritt ergreifen. Der Split View Controller umfasst die automatische Verarbeitung dieser Phase basierend auf dem Hardwaregerät. Es kann jedoch einige Sonderfälle geben, in denen der Entwickler mit dieser Änderung interagieren möchte. Durch Das Aufrufen der CollapseSecondViewController -Methode von UISplitViewControllerDelegate kann der master-Ansichtscontroller angezeigt werden, wenn der Reduzieren auftritt, anstelle der Detailansicht.

Erweitern des Geteilten Ansichtscontrollers

Sehen wir uns nun genauer an, was passiert, wenn ein Split View Controller aus einem reduzierten Zustand erweitert wird. Auch hier müssen zwei Phasen auftreten:

  • Definieren Sie zunächst den neuen primären Ansichtscontroller. Standardmäßig verwendet der Split View Controller automatisch den primären Ansichtscontroller aus der reduzierten Ansicht. Auch hier kann der Entwickler dieses Verhalten mithilfe der GetPrimaryViewControllerForExpandingSplitViewController -Methode von UISplitViewControllerDelegate überschreiben.
  • Nachdem der primäre Ansichtscontroller ausgewählt wurde, muss der sekundäre Ansichtscontroller neu erstellt werden. Auch hier umfasst der Split View Controller die automatische Verarbeitung dieser Phase basierend auf dem Hardwaregerät. Der Entwickler kann dieses Verhalten überschreiben, indem er die SeparateSecondaryViewController -Methode von UISplitViewControllerDelegate aufruft.

In einem Geteilten Ansichtscontroller spielt der primäre Ansichtscontroller eine Rolle sowohl beim Erweitern als auch beim Zusammenbrechen der Ansichten, indem er die CollapseSecondViewController Methoden und SeparateSecondaryViewController implementiert UISplitViewControllerDelegate. UINavigationController implementiert diese Methoden zum automatischen Pushen und Auffüllen des sekundären Ansichtscontrollers.

Anzeigen von Ansichtscontrollern

Eine weitere Änderung, die Apple an iOS 8 vorgenommen hat, ist die Art und Weise, wie der Entwickler Ansichtscontroller anzeigt. Wenn die Anwendung in der Vergangenheit über einen Blattansichtscontroller (z. B. einen Tabellenansichtscontroller) verfügte und der Entwickler einen anderen angezeigt hat (z. B. als Reaktion darauf, dass der Benutzer auf eine Zelle tippte), gelangte die Anwendung über die Controllerhierarchie zurück zum Navigationsansichtscontroller und ruft die PushViewController -Methode auf, um die neue Ansicht anzuzeigen.

Dies stellte eine sehr enge Kopplung zwischen dem Navigationscontroller und der Umgebung dar, in der er ausgeführt wurde. In iOS 8 hat Apple dies entkoppelt, indem es zwei neue Methoden bereitstellt:

  • ShowViewController – Passt sich an, um den neuen Ansichtscontroller basierend auf seiner Umgebung anzuzeigen. In einem UINavigationController wird beispielsweise einfach die neue Ansicht auf den Stapel verschoben. In einem Split View Controller wird der neue Ansichtscontroller auf der linken Seite als neuer primärer Ansichtscontroller angezeigt. Wenn kein Containeransichtscontroller vorhanden ist, wird die neue Ansicht als modaler Ansichtscontroller angezeigt.
  • ShowDetailViewController – Funktioniert ähnlich wie ShowViewController, wird aber in einem Split View Controller implementiert, um die Detailansicht durch den neuen Übergebenen Ansichtscontroller zu ersetzen. Wenn der Split View Controller reduziert ist (wie in einer iPhone-Anwendung zu sehen), wird der Aufruf an die ShowViewController -Methode umgeleitet, und die neue Ansicht wird als primärer Ansichtscontroller angezeigt. Wenn kein Containeransichtscontroller vorhanden ist, wird die neue Ansicht als modaler Ansichtscontroller angezeigt.

Diese Methoden funktionieren, indem sie am Blattansichtscontroller beginnen und die Ansichtshierarchie hochführen, bis sie den richtigen Containeransichtscontroller finden, um die Anzeige der neuen Ansicht zu verarbeiten.

Entwickler können und ShowDetailViewController in ihren eigenen benutzerdefinierten Ansichtscontrollern implementierenShowViewController, um die gleiche automatisierte Funktionalität zu erhalten, die und UINavigationControllerUISplitViewController bietet.

Funktionsweise

In diesem Abschnitt sehen wir uns an, wie diese Methoden tatsächlich in iOS 8 implementiert werden. Sehen wir uns zunächst die neue GetTargetForAction Methode an:

Die neue GetTargetForAction-Methode

Diese Methode führt die Hierarchiekette durch, bis der richtige Containersichtcontroller gefunden wird. Beispiel:

  1. Wenn eine ShowViewController Methode aufgerufen wird, ist der erste View Controller in der Kette, die diese Methode implementiert, der Navigationscontroller, sodass er als übergeordnetes Element der neuen Ansicht verwendet wird.
  2. Wenn stattdessen eine ShowDetailViewController Methode aufgerufen wurde, ist der Split View Controller der erste View Controller, der sie implementiert hat, sodass er als übergeordnetes Element verwendet wird.

Die GetTargetForAction -Methode sucht einen Ansichtscontroller, der eine bestimmte Aktion implementiert, und fragt dann den View Controller, ob er diese Aktion empfangen möchte. Da diese Methode öffentlich ist, können Entwickler ihre eigenen benutzerdefinierten Methoden erstellen, die genau wie die integrierten ShowViewController Methoden und ShowDetailViewController funktionieren.

Adaptive Präsentation

In iOS 8 hat Apple Popover Presentations ( UIPopoverPresentationController) ebenfalls adaptiv gemacht. Ein Popover-Präsentationsansichtscontroller stellt also automatisch eine normale Popover-Ansicht in einer regulären Größenklasse dar, zeigt sie jedoch in einer horizontal kompakten Größenklasse (z. B. auf einem iPhone) im Vollbildmodus an.

Um die Änderungen im einheitlichen Storyboardsystem zu berücksichtigen, wurde ein neues Controllerobjekt erstellt, um die angezeigten Ansichtscontroller zu verwalten – UIPresentationController. Dieser Controller wird von der Darstellung des Ansichtscontrollers bis zum Schließen erstellt. Da es sich um eine verwaltende Klasse handelt, kann sie als Superklasse über dem Ansichtscontroller betrachtet werden, da sie auf Geräteänderungen reagiert, die sich auf den Ansichtscontroller auswirken (z. B. die Ausrichtung), die dann wieder in den Ansichtscontroller des Präsentationscontroller-Steuerelements eingespeist werden.

Wenn der Entwickler mithilfe der PresentViewController -Methode einen Ansichtscontroller präsentiert, wird die Verwaltung des Präsentationsprozesses an UIKitübergeben. UIKit verarbeitet (unter anderem) den richtigen Controller für die zu erstellende Formatvorlage, wobei die einzige Ausnahme ist, wenn für einen Ansichtscontroller die Formatvorlage auf UIModalPresentationCustomfestgelegt ist. Hier kann die Anwendung ihren eigenen PresentationController bereitstellen, anstatt den UIKit Controller zu verwenden.

Benutzerdefinierte Präsentationsstile

Bei einem benutzerdefinierten Präsentationsstil haben Entwickler die Möglichkeit, einen benutzerdefinierten Präsentationscontroller zu verwenden. Dieser benutzerdefinierte Controller kann verwendet werden, um die Darstellung und das Verhalten der Ansicht zu ändern, mit der er verknüpft ist.

Arbeiten mit Größenklassen

Das Xamarin-Projekt für adaptive Fotos, das in diesem Artikel enthalten ist, enthält ein arbeitsfähiges Beispiel für die Verwendung von Größenklassen und Controllern für adaptive Ansicht in einer iOS 8 Unified Interface-Anwendung.

Während die Anwendung ihre Benutzeroberfläche vollständig aus Code erstellt, im Gegensatz zum Erstellen eines einheitlichen Storyboards mithilfe des Xcode-Schnittstellen-Generators, gelten die gleichen Techniken.

Sehen wir uns nun genauer an, wie das Adaptive Fotos-Projekt mehrere der Größenklassenfeatures in iOS 8 implementiert, um eine adaptive Anwendung zu erstellen.

Anpassung an Trait-Umgebungsänderungen

Wenn der Benutzer das Gerät beim Ausführen der Anwendung adaptive Fotos auf einem iPhone vom Hoch- in das Querformat rotiert, zeigt der Split View Controller sowohl die master- als auch die Detailansicht an:

Der Controller für geteilte Ansicht zeigt sowohl die master- als auch die Detailansicht an, wie hier dargestellt.

Dies wird erreicht, indem die UpdateConstraintsForTraitCollection -Methode des View Controller überschrieben und die Einschränkungen basierend auf dem Wert von VerticalSizeClassangepasst werden. Beispiel:

public void UpdateConstraintsForTraitCollection (UITraitCollection collection)
{
    var views = NSDictionary.FromObjectsAndKeys (
        new object[] { TopLayoutGuide, ImageView, NameLabel, ConversationsLabel, PhotosLabel },
        new object[] { "topLayoutGuide", "imageView", "nameLabel", "conversationsLabel", "photosLabel" }
    );

    var newConstraints = new List<NSLayoutConstraint> ();
    if (collection.VerticalSizeClass == UIUserInterfaceSizeClass.Compact) {
        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|[imageView]-[nameLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("[imageView]-[conversationsLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("[imageView]-[photosLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("V:|[topLayoutGuide]-[nameLabel]-[conversationsLabel]-[photosLabel]",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("V:|[topLayoutGuide][imageView]|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.Add (NSLayoutConstraint.Create (ImageView, NSLayoutAttribute.Width, NSLayoutRelation.Equal,
            View, NSLayoutAttribute.Width, 0.5f, 0.0f));
    } else {
        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|[imageView]|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|-[nameLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|-[conversationsLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|-[photosLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("V:[topLayoutGuide]-[nameLabel]-[conversationsLabel]-[photosLabel]-20-[imageView]|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));
    }

    if (constraints != null)
        View.RemoveConstraints (constraints.ToArray ());

    constraints = newConstraints;
    View.AddConstraints (constraints.ToArray ());
}

Hinzufügen von Übergangsanimationen

Wenn der Split View Controller in der Anwendung "Adaptive Fotos" von "reduziert" zu "erweitert" wechselt, werden Animationen zu den Standardanimationen hinzugefügt, indem die WillTransitionToTraitCollection Methode des Ansichtscontrollers überschrieben wird. Beispiel:

public override void WillTransitionToTraitCollection (UITraitCollection traitCollection, IUIViewControllerTransitionCoordinator coordinator)
{
    base.WillTransitionToTraitCollection (traitCollection, coordinator);
    coordinator.AnimateAlongsideTransition ((UIViewControllerTransitionCoordinatorContext) => {
        UpdateConstraintsForTraitCollection (traitCollection);
        View.SetNeedsLayout ();
    }, (UIViewControllerTransitionCoordinatorContext) => {
    });
}

Überschreiben der Trait-Umgebung

Wie oben gezeigt, erzwingt die Anwendung adaptive Fotos, dass der Split View Controller sowohl die Details als auch die master Ansichten anzeigt, wenn sich das iPhone-Gerät in der Queransicht befindet.

Dies wurde mithilfe des folgenden Codes im Ansichtscontroller erreicht:

private UITraitCollection forcedTraitCollection = new UITraitCollection ();
...

public UITraitCollection ForcedTraitCollection {
    get {
        return forcedTraitCollection;
    }

    set {
        if (value != forcedTraitCollection) {
            forcedTraitCollection = value;
            UpdateForcedTraitCollection ();
        }
    }
}
...

public override void ViewWillTransitionToSize (SizeF toSize, IUIViewControllerTransitionCoordinator coordinator)
{
    ForcedTraitCollection = toSize.Width > 320.0f ?
         UITraitCollection.FromHorizontalSizeClass (UIUserInterfaceSizeClass.Regular) :
         new UITraitCollection ();

    base.ViewWillTransitionToSize (toSize, coordinator);
}

public void UpdateForcedTraitCollection ()
{
    SetOverrideTraitCollection (forcedTraitCollection, viewController);
}

Erweitern und Reduzieren des Geteilten Ansichtscontrollers

Als Nächstes untersuchen wir, wie das Expanding- und Kollapsverhalten des Split View Controller in Xamarin implementiert wurde. Wenn der Split View Controller erstellt wird, wird sein AppDelegateDelegat zugewiesen, um die folgenden Änderungen zu behandeln:

public class SplitViewControllerDelegate : UISplitViewControllerDelegate
{
    public override bool CollapseSecondViewController (UISplitViewController splitViewController,
        UIViewController secondaryViewController, UIViewController primaryViewController)
    {
        AAPLPhoto photo = ((CustomViewController)secondaryViewController).Aapl_containedPhoto (null);
        if (photo == null) {
            return true;
        }

        if (primaryViewController.GetType () == typeof(CustomNavigationController)) {
            var viewControllers = new List<UIViewController> ();
            foreach (var controller in ((UINavigationController)primaryViewController).ViewControllers) {
                var type = controller.GetType ();
                MethodInfo method = type.GetMethod ("Aapl_containsPhoto");

                if ((bool)method.Invoke (controller, new object[] { null })) {
                    viewControllers.Add (controller);
                }
            }

            ((UINavigationController)primaryViewController).ViewControllers = viewControllers.ToArray<UIViewController> ();
        }

        return false;
    }

    public override UIViewController SeparateSecondaryViewController (UISplitViewController splitViewController,
        UIViewController primaryViewController)
    {
        if (primaryViewController.GetType () == typeof(CustomNavigationController)) {
            foreach (var controller in ((CustomNavigationController)primaryViewController).ViewControllers) {
                var type = controller.GetType ();
                MethodInfo method = type.GetMethod ("Aapl_containedPhoto");

                if (method.Invoke (controller, new object[] { null }) != null) {
                    return null;
                }
            }
        }

        return new AAPLEmptyViewController ();
    }
}

Die SeparateSecondaryViewController -Methode testet, um festzustellen, ob ein Foto angezeigt wird, und führt basierend auf diesem Zustand Aktionen aus. Wenn kein Foto angezeigt wird, wird der sekundäre Ansichtscontroller reduziert, sodass der Masteransichtscontroller angezeigt wird.

Die CollapseSecondViewController -Methode wird beim Erweitern des Split View Controller verwendet, um festzustellen, ob Fotos auf dem Stapel vorhanden sind. Wenn dies der Fall ist, wird sie in diese Ansicht zurückgeklappt.

Wechseln zwischen Ansichtscontrollern

Als Nächstes sehen wir uns an, wie sich die Adaptive Photos-Anwendung zwischen Ansichtscontrollern bewegt. Wenn der Benutzer in der AAPLConversationViewController -Klasse eine Zelle aus der Tabelle auswählt, wird die ShowDetailViewController -Methode aufgerufen, um die Detailansicht anzuzeigen:

public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
    var photo = PhotoForIndexPath (indexPath);
    var controller = new AAPLPhotoViewController ();
    controller.Photo = photo;

    int photoNumber = indexPath.Row + 1;
    int photoCount = (int)Conversation.Photos.Count;
    controller.Title = string.Format ("{0} of {1}", photoNumber, photoCount);
    ShowDetailViewController (controller, this);
}

Anzeigen von Offenlegungsindikatoren

In der Anwendung adaptives Foto gibt es mehrere Stellen, an denen Offenlegungsindikatoren ausgeblendet oder basierend auf Änderungen an der Trait-Umgebung angezeigt werden. Dies wird mit dem folgenden Code behandelt:

public bool Aapl_willShowingViewControllerPushWithSender ()
{
    var selector = new Selector ("Aapl_willShowingViewControllerPushWithSender");
    var target = this.GetTargetViewControllerForAction (selector, this);

    if (target != null) {
        var type = target.GetType ();
        MethodInfo method = type.GetMethod ("Aapl_willShowingDetailViewControllerPushWithSender");
        return (bool)method.Invoke (target, new object[] { });
    } else {
        return false;
    }
}

public bool Aapl_willShowingDetailViewControllerPushWithSender ()
{
    var selector = new Selector ("Aapl_willShowingDetailViewControllerPushWithSender");
    var target = this.GetTargetViewControllerForAction (selector, this);

    if (target != null) {
        var type = target.GetType ();
        MethodInfo method = type.GetMethod ("Aapl_willShowingDetailViewControllerPushWithSender");
        return (bool)method.Invoke (target, new object[] { });
    } else {
        return false;
    }
}

Diese werden mithilfe der GetTargetViewControllerForAction oben ausführlich erläuterten Methode implementiert.

Wenn ein Tabellenansichtscontroller Daten anzeigt, verwendet er die oben implementierten Methoden, um zu ermitteln, ob ein Push erfolgt oder nicht, und ob der Offenlegungsindikator entsprechend angezeigt oder ausgeblendet werden soll:

public override void WillDisplay (UITableView tableView, UITableViewCell cell, NSIndexPath indexPath)
{
    bool pushes = ShouldShowConversationViewForIndexPath (indexPath) ?
         Aapl_willShowingViewControllerPushWithSender () :
         Aapl_willShowingDetailViewControllerPushWithSender ();

    cell.Accessory = pushes ? UITableViewCellAccessory.DisclosureIndicator : UITableViewCellAccessory.None;
    var conversation = ConversationForIndexPath (indexPath);
    cell.TextLabel.Text = conversation.Name;
}

Neuer ShowDetailTargetDidChangeNotification Typ

Apple hat einen neuen Benachrichtigungstyp für die Arbeit mit Größenklassen und Trait-Umgebungen in einem Split View Controller ShowDetailTargetDidChangeNotificationhinzugefügt. Diese Benachrichtigung wird gesendet, wenn sich die Zieldetailseite für einen Split View Controller ändert, z. B. wenn der Controller erweitert oder reduziert wird.

Die Anwendung adaptive Fotos verwendet diese Benachrichtigung, um den Status des Offenlegungsindikators zu aktualisieren, wenn sich der Detailansichtscontroller ändert:

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    TableView.RegisterClassForCellReuse (typeof(UITableViewCell), AAPLListTableViewControllerCellIdentifier);
    NSNotificationCenter.DefaultCenter.AddObserver (this, new Selector ("showDetailTargetDidChange:"),
        UIViewController.ShowDetailTargetDidChangeNotification, null);
    ClearsSelectionOnViewWillAppear = false;
}

Sehen Sie sich die Adaptive Fotos-Anwendung genauer an, um alle Möglichkeiten zu sehen, wie Größenklassen, Trait-Sammlungen und Controller für die adaptive Ansicht zum einfachen Erstellen einer einheitlichen Anwendung in Xamarin.iOS verwendet werden können.

Einheitliche Storyboards

Mit Unified Storyboards, die in iOS 8 neu sind, können Entwickler eine einheitliche Storyboarddatei erstellen, die sowohl auf iPhone- als auch auf iPad-Geräten angezeigt werden kann, indem mehrere Größenklassen verwendet werden. Durch die Verwendung von Unified Storyboards schreibt der Entwickler weniger benutzeroberflächenspezifischen Code und verfügt über nur ein Schnittstellendesign, das erstellt und verwaltet werden muss.

Die wichtigsten Vorteile von Unified Storyboards sind:

  • Verwenden Sie dieselbe Storyboarddatei für iPhone und iPad.
  • Stellen Sie die Bereitstellung rückwärts für iOS 6 und iOS 7 bereit.
  • Zeigen Sie eine Vorschau des Layouts für verschiedene Geräte, Ausrichtungen und Betriebssystemversionen an.

Aktivieren von Größenklassen

Standardmäßig verwendet jedes neue Xamarin.iOS-Projekt Größenklassen. Um Größenklassen und adaptive Segues in einem Storyboard aus einem älteren Projekt zu verwenden, muss es zuerst in das Xcode 6 Unified Storyboard-Format konvertiert werden, und das Kontrollkästchen Größenklassen verwenden ist im Xcode-Dateiinspektor für Ihre Storyboards aktiviert.

Dynamische Startbildschirme

Die Startbildschirmdatei wird als Begrüßungsbildschirm angezeigt, während eine iOS-Anwendung gestartet wird, um dem Benutzer Feedback zu geben, dass die App tatsächlich gestartet wird. Vor iOS 8 musste der Entwickler mehrere Default.png Bildressourcen für jeden Gerätetyp, jede Ausrichtung und bildschirmauflösung einschließen, auf der die Anwendung ausgeführt wird. Beispiel: Default@2x.png, Default-Landscape@2x~ipad.png, Default-Portrait@2x~ipad.pngusw.

Wenn die neuen iPhone 6- und iPhone 6 Plus-Geräte (und die kommende Apple Watch) mit allen vorhandenen iPhone- und iPad-Geräten einbehalten werden, stellt dies eine große Auswahl unterschiedlicher Größen, Ausrichtungen und Auflösungen von Default.png Startbildschirm-Bildressourcen dar, die erstellt und verwaltet werden müssen. Darüber hinaus können diese Dateien sehr groß sein und das lieferumfangbare Anwendungspaket "aufblähen", was die Zeit erhöht, die zum Herunterladen der Anwendung aus dem iTunes-App Store benötigt wird (möglicherweise verhindert, dass sie über ein Mobilfunknetzwerk übermittelt werden kann) und die auf dem Gerät des Endbenutzers erforderliche Speichermenge erhöht.

Neu bei iOS 8 kann der Entwickler eine einzelne, atomare .xib Datei in Xcode erstellen, die autolayout- und größenklassen verwendet, um einen dynamischen Startbildschirm zu erstellen, der für jedes Gerät, jede Auflösung und ausrichtung funktioniert. Dies reduziert nicht nur den Aufwand, den der Entwickler zum Erstellen und Verwalten aller erforderlichen Imageressourcen benötigt, sondern auch die Größe des installierten Pakets der Anwendung erheblich.

Dynamische Startbildschirme weisen die folgenden Einschränkungen und Überlegungen auf:

  • Verwenden Sie nur UIKit Klassen.
  • Verwenden Sie eine einzelne Stammansicht, bei der es sich um ein UIView - oder UIViewController -Objekt handelt.
  • Stellen Sie keine Verbindungen mit dem Code der Anwendung (fügen Sie keine Aktionen oder Outlets hinzu).
  • Fügen Sie keine Objekte hinzu UIWebView .
  • Verwenden Sie keine benutzerdefinierten Klassen.
  • Verwenden Sie keine Laufzeitattribute.

Unter Berücksichtigung der oben genannten Richtlinien sehen wir uns das Hinzufügen eines dynamischen Startbildschirms zu einem vorhandenen Xamarin iOS 8-Projekt an.

Gehen Sie folgendermaßen vor:

  1. Öffnen Sie Visual Studio für Mac, und laden Sie die Projektmappe, um den dynamischen Startbildschirm hinzuzufügen.

  2. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf die MainStoryboard.storyboard Datei, und wählen Sie Mit>Xcode-Schnittstellen-Generator öffnen aus:

    Öffnen mit Xcode-Schnittstellen-Generator

  3. Wählen Sie in Xcode Datei>Neue>Datei... aus:

    Datei/Neu auswählen

  4. Wählen SieiOS-Benutzeroberfläche>>Startbildschirm aus, und klicken Sie auf die Schaltfläche Weiter:

    Auswählen von iOS/Benutzeroberfläche/Startbildschirm

  5. Nennen Sie die Datei, LaunchScreen.xib und klicken Sie auf die Schaltfläche Erstellen :

    Nennen Sie die Datei LaunchScreen.xib

  6. Bearbeiten Sie den Entwurf des Startbildschirms, indem Sie Grafische Elemente hinzufügen und Layouteinschränkungen verwenden, um sie für die angegebenen Geräte, Ausrichtungen und Bildschirmgrößen zu positionieren:

    Bearbeiten des Entwurfs des Startbildschirms

  7. Speichern Sie die Änderungen in LaunchScreen.xib.

  8. Wählen Sie die Registerkarte Anwendungsziel und Allgemein aus:

    Wählen Sie die Registerkarte Anwendungsziel und Allgemein aus.

  9. Klicken Sie auf die Schaltfläche Info.plist auswählen , wählen Sie die Info.plist für die Xamarin-App aus, und klicken Sie auf die Schaltfläche Auswählen :

    Wählen Sie info.plist für die Xamarin-App aus.

  10. Öffnen Sie im Abschnitt App-Symbole und Bilder starten die Dropdownliste Datei des Startbildschirms , und wählen Sie das LaunchScreen.xib oben erstellte aus:

    Wählen Sie launchScreen.xib aus.

  11. Speichern Sie die Änderungen an der Datei, und kehren Sie zu Visual Studio für Mac zurück.

  12. Warten Sie, bis Visual Studio für Mac die Synchronisierung der Änderungen mit Xcode abgeschlossen hat.

  13. Klicken Sie im Projektmappen-Explorer mit der rechten Maustaste auf den Ordner Ressource, und wählen SieDateien hinzufügen>... aus:

    Wählen Sie Dateien hinzufügen/hinzufügen... aus.

  14. Wählen Sie die LaunchScreen.xib oben erstellte Datei aus, und klicken Sie auf die Schaltfläche Öffnen :

    Wählen Sie die Datei LaunchScreen.xib aus.

  15. Erstellen Sie die Anwendung.

Testen des dynamischen Startbildschirms

Wählen Sie in Visual Studio für Mac den iPhone 4 Retina-Simulator aus, und führen Sie die Anwendung aus. Der dynamische Startbildschirm wird im richtigen Format und in der richtigen Ausrichtung angezeigt:

Der dynamische Startbildschirm, der in der vertikalen Ausrichtung angezeigt wird

Beenden Sie die Anwendung in Visual Studio für Mac, und wählen Sie ein iPad iOS 8-Gerät aus. Führen Sie die Anwendung aus, und der Startbildschirm wird für dieses Gerät und die Ausrichtung ordnungsgemäß formatiert:

Der dynamische Startbildschirm, der in der horizontalen Ausrichtung angezeigt wird

Kehren Sie zu Visual Studio für Mac zurück, und beenden Sie die Ausführung der Anwendung.

Arbeiten mit iOS 7

Um die Abwärtskompatibilität mit iOS 7 zu gewährleisten, fügen Sie einfach die üblichen Default.png Bildressourcen wie gewohnt in die iOS 8-Anwendung ein. iOS kehrt zum vorherigen Verhalten zurück und verwendet diese Dateien als Startbildschirm, wenn sie auf einem iOS 7-Gerät ausgeführt werden.

Um eine Implementierung eines dynamischen Startbildschirms in Xamarin anzuzeigen, sehen Sie sich die diesem Dokument angefügte Beispielanwendung für dynamische Startbildschirme für iOS 8 an.

Zusammenfassung

In diesem Artikel wurden Größenklassen und deren Auswirkungen auf das Layout von iPhone- und iPad-Geräten kurz erläutert. Es wurde erläutert, wie Merkmale, Traitumgebungen und Traitsammlungen mit Größenklassen funktionieren, um einheitliche Schnittstellen zu erstellen. Es wurde ein kurzer Blick auf Adaptive View-Controller und deren Funktionsweise mit Größenklassen innerhalb von einheitlichen Schnittstellen genommen. Es wurde untersucht, größenklassen und einheitliche Schnittstellen vollständig aus C#-Code in einer Xamarin iOS 8-Anwendung zu implementieren.

Schließlich behandelt dieser Artikel die Grundlagen zum Erstellen eines einzelnen dynamischen Startbildschirms, der als Startbildschirm auf jedem iOS 8-Gerät angezeigt wird.