Ujednolicone scenorysy w środowisku Xamarin.iOS

System iOS 8 zawiera nowy, prostszy mechanizm tworzenia interfejsu użytkownika — ujednoliconego scenorysu. W przypadku pojedynczego scenorysu obejmującego wszystkie różne rozmiary ekranu sprzętowego można utworzyć szybkie i dynamiczne widoki w stylu "raz do projektowania i używania wielu".

Ponieważ deweloper nie musi już tworzyć oddzielnego i konkretnego scenorysu dla urządzeń i Telefon i iPad, mają elastyczność projektowania aplikacji za pomocą wspólnego interfejsu, a następnie dostosowywania tego interfejsu dla różnych klas rozmiarów. W ten sposób można dostosować aplikację do mocnych stron każdego czynnika formularza, a każdy interfejs użytkownika można dostosować w celu zapewnienia najlepszego środowiska.

Klasy rozmiarów

Przed systemem iOS 8 deweloper używał UIInterfaceOrientation i UIInterfaceIdiom rozróżniał tryby pionowe i poziome oraz między urządzeniami i Telefon i iPad. W systemie iOS8 orientacja i urządzenie jest określane przy użyciu klas rozmiarów.

Urządzenia są definiowane przez klasy rozmiarów, zarówno w osiach pionowych, jak i poziomych, a w systemie iOS 8 istnieją dwa typy klas rozmiarów:

  • Regularne — dotyczy to dużego rozmiaru ekranu (na przykład tabletu iPad) lub gadżetu, który sprawia wrażenie dużego rozmiaru (takiego jak UIScrollView
  • Compact — dotyczy to mniejszych urządzeń (takich jak i Telefon). Ten rozmiar uwzględnia orientację urządzenia.

Jeśli te dwie koncepcje są używane razem, wynikiem jest siatka 2 x 2, która definiuje różne możliwe rozmiary, które mogą być używane w obu różnych orientacjach, jak pokazano na poniższym diagramie:

Siatka 2 x 2, która definiuje różne możliwe rozmiary, które mogą być używane w orientacjach regularnych i kompaktowych

Deweloper może utworzyć kontroler widoku, który korzysta z dowolnego z czterech możliwości, które mogłyby spowodować różne układy (jak pokazano na powyższej grafice).

Klasy rozmiarów tabletu iPad

Tablet iPad ze względu na rozmiar ma zwykły rozmiar klasy dla obu orientacji.

Klasy rozmiarów tabletu iPad

i Telefon Klasy rozmiarów

Klasa i Telefon ma różne klasy rozmiarów na podstawie orientacji urządzenia:

i Telefon Klasy rozmiarów

  • Gdy urządzenie jest w trybie pionowym, ekran ma kompaktową klasę w poziomie i regularnie w pionie
  • Gdy urządzenie jest w trybie poziomym, klasy ekranu są odwracane z trybu pionowego.

i Telefon 6 plus klasy rozmiarów

Rozmiary są takie same jak w przypadku wcześniejszych wartości i Telefon w orientacji pionowej, ale różnią się w poziomie:

i Telefon 6 plus klasy rozmiarów

Ponieważ i Telefon 6 Plus ma wystarczająco duży ekran, jest w stanie mieć klasę Rozmiar szerokości regularnej w trybie poziomym.

Obsługa nowej skali ekranu

I Telefon 6 Plus używa nowego wyświetlacza Retina HD ze współczynnikiem skali ekranu 3,0 (trzy razy oryginalna rozdzielczość ekranu i Telefon). Aby zapewnić najlepsze możliwe środowisko na tych urządzeniach, dołącz nową grafikę zaprojektowaną na potrzeby tej skali ekranu. W programie Xcode 6 lub nowszym wykazy zasobów mogą zawierać obrazy o rozmiarze 1x, 2x i 3x; Po prostu dodaj nowe zasoby obrazów i system iOS wybierze odpowiednie zasoby podczas uruchamiania w systemie i Telefon 6 Plus.

Zachowanie ładowania obrazu w systemie iOS rozpoznaje również sufiks w plikach @3x obrazów. Jeśli na przykład deweloper zawiera zasób obrazu (w różnych rozdzielczościach) w pakiecie aplikacji z następującymi nazwami plików: MonkeyIcon.png, MonkeyIcon@2x.pngi MonkeyIcon@3x.png. W pliku i Telefon 6 Plus MonkeyIcon@3x.png obraz zostanie użyty automatycznie, jeśli deweloper ładuje obraz przy użyciu następującego kodu:

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

Dynamiczne ekrany uruchamiania

Plik ekranu uruchamiania jest wyświetlany jako ekran powitalny podczas uruchamiania aplikacji systemu iOS w celu przekazania opinii użytkownikowi, że aplikacja rzeczywiście uruchamia się. Przed systemem iOS 8 deweloper musiałby uwzględnić wiele Default.png zasobów obrazów dla każdego typu urządzenia, orientacji i rozdzielczości ekranu, na którym będzie uruchomiona aplikacja.

Nowy dla systemu iOS 8 deweloper może utworzyć pojedynczy, niepodzielny .xib plik w programie Xcode, który używa klas automatycznego układu i rozmiaru do tworzenia dynamicznego ekranu uruchamiania, który będzie działać dla każdego urządzenia, rozdzielczości i orientacji. Zmniejsza to nie tylko ilość pracy wymaganej przez dewelopera do tworzenia i obsługi wszystkich wymaganych zasobów obrazów, ale zmniejsza rozmiar zainstalowanego pakietu aplikacji.

Cechy

Cechy to właściwości, których można użyć do określenia, jak zmienia się układ w miarę zmian w środowisku. Składają się one z zestawu właściwości (i HorizontalSizeClassVerticalSizeClass na UIUserInterfaceSizeClasspodstawie ), a także interfejsu idiom ( UIUserInterfaceIdiom) i skali wyświetlania.

Wszystkie powyższe stany są opakowane w kontenerze, który apple odnosi się do kolekcji cech ( UITraitCollection), która zawiera nie tylko właściwości, ale także ich wartości.

Środowisko cech

Środowiska cech to nowy interfejs w systemie iOS 8 i mogą zwracać kolekcję cech dla następujących obiektów:

  • Ekrany ( UIScreens ).
  • Windows ( UIWindows ).
  • Kontrolery widoku ( UIViewController ).
  • Widoki ( UIView ).
  • Kontroler prezentacji ( UIPresentationController ).

Deweloper używa kolekcji cech zwracanych przez środowisko cech, aby określić sposób programowania interfejsu użytkownika.

Wszystkie środowiska cech tworzą hierarchię, jak pokazano na poniższym diagramie:

Diagram hierarchii środowisk cech

Kolekcja cech, które mają wszystkie powyższe środowiska cech, będzie domyślnie przepływać z elementu nadrzędnego do środowiska podrzędnego.

Oprócz pobierania bieżącej kolekcji cech środowisko cech ma metodę TraitCollectionDidChange , którą można zastąpić w podklasach Widok lub Kontroler widoku. Deweloper może użyć tej metody, aby zmodyfikować dowolny element interfejsu użytkownika, który zależy od cech, gdy te cechy uległy zmianie.

Typowe kolekcje cech

W tej sekcji omówiono typowe typy kolekcji cech, które użytkownik będzie doświadczał podczas pracy z systemem iOS 8.

Poniżej przedstawiono typową kolekcję cech, którą deweloper może zobaczyć na karcie i Telefon:

Właściwości Wartość
HorizontalSizeClass CD
VerticalSizeClass Zwykły
UserInterfaceIdom Phone
DisplayScale 2.0

Powyższy zestaw będzie reprezentować w pełni kwalifikowaną kolekcję cech, ponieważ ma wartości dla wszystkich jej właściwości cech.

Istnieje również możliwość posiadania kolekcji cech, której brakuje niektórych wartości (które firma Apple określa jako nieokreślone):

Właściwości Wartość
HorizontalSizeClass CD
VerticalSizeClass Nieokreślony
UserInterfaceIdom Nieokreślony
DisplayScale Nieokreślony

Ogólnie jednak, gdy deweloper pyta środowisko cech dla kolekcji cech, zwróci w pełni kwalifikowaną kolekcję, jak pokazano w powyższym przykładzie.

Jeśli środowisko cech (na przykład widok lub kontroler widoku) nie znajduje się w bieżącej hierarchii widoków, deweloper może wrócić do nieokreślonych wartości dla co najmniej jednej właściwości cechy.

Deweloper otrzyma również częściowo kwalifikowaną kolekcję cech, jeśli użyje jednej z metod tworzenia udostępnianych przez firmę Apple, takiej jak UITraitCollection.FromHorizontalSizeClass, w celu utworzenia nowej kolekcji.

Jedna operacja, którą można wykonać w wielu kolekcjach cech, porównuje je ze sobą, co polega na pytaniu o jedną kolekcję cech, jeśli zawiera inną. Oznacza to , że dla każdej cechy określonej w drugiej kolekcji wartość musi być dokładnie zgodna z wartością w pierwszej kolekcji.

Aby przetestować dwie cechy, użyj Contains metody UITraitCollection przekazywania wartości cech do przetestowania.

Deweloper może wykonać porównania ręcznie w kodzie, aby określić sposób układu widoków lub kontrolerów widoku. Jednak używa tej metody wewnętrznie, UIKit aby zapewnić niektóre jej funkcje, jak na przykład w serwerze proxy wyglądu.

Serwer proxy wyglądu

Serwer proxy wyglądu został wprowadzony we wcześniejszych wersjach systemu iOS, aby umożliwić deweloperom dostosowywanie właściwości ich widoków. Rozszerzono go w systemie iOS 8, aby obsługiwać kolekcje cech.

Serwery proxy wyglądu zawierają teraz nową metodę , AppearanceForTraitCollectionktóra zwraca nowy serwer proxy wyglądu dla danej kolekcji cech, która została przekazana. Wszelkie dostosowania wykonywane przez dewelopera na tym serwerze proxy wyglądu będą obowiązywać tylko na widokach zgodnych z określoną kolekcją cech.

Zazwyczaj deweloper przekaże częściowo określoną kolekcję cech do AppearanceForTraitCollection metody, na przykład taką, która właśnie określiła klasę rozmiaru poziomego compact, aby umożliwić dostosowanie dowolnego widoku w aplikacji, który jest kompaktowy w poziomie.

UIImage

Inną klasą, do którego firma Apple dodała kolekcję cech, jest UIImage. W przeszłości deweloper musiał określić @1X i @2x wersję dowolnego elementu graficznego z mapą bitową, który miał zawierać w aplikacji (np. ikonę).

System iOS 8 został rozszerzony, aby umożliwić deweloperowi dołączenie wielu wersji obrazu do wykazu obrazów na podstawie kolekcji cech. Na przykład deweloper może dołączyć mniejszy obraz do pracy z klasą Compact Trait i pełnowymiarowym obrazem dla każdej innej kolekcji.

Gdy jeden z obrazów jest używany wewnątrz UIImageView klasy, widok obrazu automatycznie wyświetli poprawną wersję obrazu dla kolekcji cech. Jeśli środowisko trait zmieni się (na przykład użytkownik przełączający urządzenie z pionowego na poziomy), widok obrazu automatycznie wybierze nowy rozmiar obrazu, aby dopasować nowy rozmiar kolekcji cech i zmienić jego rozmiar tak, aby był zgodny z bieżącą wersją wyświetlanego obrazu.

UIImageAsset

Firma Apple dodała nową klasę do systemu iOS 8 o nazwie UIImageAsset , aby zapewnić deweloperowi jeszcze większą kontrolę nad wyborem obrazu.

Zasób obrazu opakowuje wszystkie różne wersje obrazu i pozwala deweloperowi poprosić o określony obraz zgodny z przekazaną kolekcją cech. Obrazy można dodawać lub usuwać z zasobu obrazu na bieżąco.

Aby uzyskać więcej informacji na temat zasobów obrazów, zobacz dokumentację UIImageAsset firmy Apple.

Łączenie kolekcji cech

Inną funkcją, którą deweloper może wykonać w kolekcjach cech, jest dodanie dwóch razem, które spowoduje połączenie kolekcji, gdzie nieokreślone wartości z jednej kolekcji są zastępowane przez określone wartości w drugim. Odbywa się to przy użyciu FromTraitsFromCollections metody UITraitCollection klasy .

Jak wspomniano powyżej, jeśli którakolwiek z cech nie jest określona w jednej z kolekcji cech i jest określona w innej, wartość zostanie ustawiona na określoną wersję. Jeśli jednak określono wiele wersji danej wartości, wartość z ostatniej kolekcji cech będzie wartością, która jest używana.

Kontrolery widoku adaptacyjnego

W tej sekcji omówiono sposób, w jaki kontrolery widoków i widoków systemu iOS przyjęły koncepcje klas cech i rozmiarów, aby automatycznie być bardziej adaptacyjne w aplikacjach dewelopera.

Kontroler widoku podzielonego

Jedną z klas kontrolera widoku, która zmieniła najbardziej w systemie iOS 8, jest UISplitViewController klasa . W przeszłości deweloper często używał kontrolera widoku podzielonego w wersji aplikacji iPad, a następnie musiałby zapewnić zupełnie inną wersję hierarchii widoków dla aplikacji i Telefon.

W systemie iOS 8 UISplitViewController klasa jest dostępna na obu platformach (iPad i i Telefon), co pozwala deweloperowi utworzyć jedną hierarchię kontrolera widoku, która będzie działać zarówno dla systemów i Telefon, jak i iPad.

Gdy element i Telefon znajduje się w widoku poziomym, kontroler widoku podzielonego będzie prezentować widoki obok siebie, podobnie jak w przypadku wyświetlania na urządzeniu iPad.

Zastępowanie cech

Środowiska cech kaskadowe z kontenera nadrzędnego do kontenerów podrzędnych, podobnie jak na poniższej ilustracji przedstawiającej kontroler widoku podzielonego na urządzeniu iPad w orientacji poziomej:

Kontroler widoku podzielonego na urządzeniu iPad w orientacji poziomej

Ponieważ tablet iPad ma klasę Zwykłego rozmiaru zarówno w orientacji poziomej, jak i pionowej, widok podzielony będzie wyświetlać zarówno widoki wzorca, jak i szczegółów.

W tabeli i Telefon, gdzie klasa Size Class jest kompaktowana w obu orientacjach, kontroler widoku podzielonego wyświetla tylko widok szczegółów, jak pokazano poniżej:

Kontroler widoku podzielonego wyświetla tylko widok szczegółów

W aplikacji, w której deweloper chce wyświetlić zarówno widok główny, jak i szczegółowy w orientacji i Telefon w orientacji poziomej, deweloper musi wstawić kontener nadrzędny dla kontrolera widoku podzielonego i przesłonić kolekcję cech. Jak pokazano na poniższej ilustracji:

Deweloper musi wstawić kontener nadrzędny dla kontrolera widoku podzielonego i zastąpić kolekcję cech

Element UIView jest ustawiony jako element nadrzędny kontrolera widoku podzielonego, a SetOverrideTraitCollection metoda jest wywoływana w widoku przekazującym nową kolekcję cech i określania wartości docelowej kontrolera widoku podzielonego. Nowa kolekcja cech zastępuje HorizontalSizeClasselement , ustawiając go na Regular, tak aby kontroler widoku podzielonego wyświetlał zarówno widoki wzorca, jak i szczegółów w orientacji poziomej i Telefon.

Należy pamiętać, że VerticalSizeClass parametr został ustawiony na unspecifiedwartość , co umożliwia dodanie nowej kolekcji cech do kolekcji cech w obiekcie nadrzędnym, co spowoduje, Compact VerticalSizeClass że element dla podrzędnego kontrolera widoku podzielonego.

Zmiany cech

W tej sekcji przyjrzymy się szczegółowo sposobowi przejścia kolekcji cech po zmianie środowiska cech. Na przykład gdy urządzenie jest obracane z pionowego na poziome.

Przegląd zmian cech pionowych i cech poziomych

Najpierw system iOS 8 wykonuje pewne czynności konfiguracyjne, aby przygotować się do przejścia. Następnie system animuje stan przejścia. Na koniec system iOS 8 czyści wszystkie stany tymczasowe wymagane podczas przejścia.

System iOS 8 udostępnia kilka wywołań zwrotnych, których deweloper może użyć do udziału w zmianie cech, jak pokazano w poniższej tabeli:

Faza Oddzwanianie opis
Ustawienia
  • WillTransitionToTraitCollection
  • TraitCollectionDidChange
  • Ta metoda jest wywoływana na początku zmiany cech, zanim kolekcja cech zostanie ustawiona na nową wartość.
  • Metoda jest wywoływana, gdy wartość kolekcji cech uległa zmianie, ale przed rozpoczęciem animacji.
Animacja WillTransitionToTraitCollection Koordynator przejścia przekazywany do tej metody ma AnimateAlongside właściwość, która umożliwia deweloperowi dodawanie animacji, które zostaną wykonane wraz z domyślnymi animacjami.
Czyszczenie WillTransitionToTraitCollection Udostępnia deweloperom metodę dołączania własnego kodu oczyszczania po zakończeniu przejścia.

Metoda WillTransitionToTraitCollection doskonale nadaje się do animowania kontrolerów widoku wraz ze zmianami kolekcji cech. Metoda WillTransitionToTraitCollection jest dostępna tylko w kontrolerach widoku ( UIViewController) i nie w innych środowiskach cech, takich jak UIViews.

Doskonale TraitCollectionDidChange nadaje się do pracy z klasą UIView , w której deweloper chce zaktualizować interfejs użytkownika w miarę zmieniania się cech.

Zwijanie kontrolerów widoku podzielonego

Teraz przyjrzyjmy się bliżej temu, co się stanie, gdy kontroler widoku podzielonego zwinie się z dwóch kolumn do jednego widoku kolumny. W ramach tej zmiany istnieją dwa procesy, które muszą wystąpić:

  • Domyślnie kontroler widoku podzielonego będzie używać podstawowego kontrolera widoku jako widoku po upadku. Deweloper może zastąpić to zachowanie, przesłaniając GetPrimaryViewControllerForCollapsingSplitViewController metodę UISplitViewControllerDelegate obiektu i podając dowolny kontroler widoku, który ma być wyświetlany w stanie zwiniętym.
  • Kontroler widoku pomocniczego musi zostać scalony z kontrolerem widoku podstawowego. Ogólnie rzecz biorąc, deweloper nie musi podejmować żadnych działań w tym kroku; Kontroler widoku podzielonego obejmuje automatyczną obsługę tej fazy na podstawie urządzenia sprzętowego. Może jednak istnieć kilka specjalnych przypadków, w których deweloper będzie chciał wchodzić w interakcję z tą zmianą. CollapseSecondViewController Wywołanie metody metody UISplitViewControllerDelegate umożliwia wyświetlanie kontrolera widoku głównego w momencie wystąpienia zwijania zamiast widoku szczegółów.

Rozszerzanie kontrolera widoku podzielonego

Teraz przyjrzyjmy się bliżej temu, co się stanie po rozwinięciu kontrolera widoku podzielonego z zwiniętego stanu. Po raz kolejny istnieją dwa etapy, które muszą wystąpić:

  • Najpierw zdefiniuj nowy kontroler widoku podstawowego. Domyślnie kontroler widoku podzielonego będzie automatycznie używać kontrolera widoku podstawowego z zwiniętego widoku. Ponownie deweloper może zastąpić to zachowanie przy użyciu GetPrimaryViewControllerForExpandingSplitViewController metody UISplitViewControllerDelegate .
  • Po wybraniu kontrolera widoku podstawowego należy ponownie utworzyć kontroler widoku pomocniczego. Ponownie kontroler widoku podzielonego obejmuje automatyczną obsługę tej fazy na podstawie urządzenia sprzętowego. Deweloper może zastąpić to zachowanie, wywołując metodę SeparateSecondaryViewController .UISplitViewControllerDelegate

W kontrolerze widoku podzielonego kontroler widoku podstawowego odgrywa rolę zarówno w rozszerzaniu i zwijania widoków przez zaimplementowanie CollapseSecondViewController metod UISplitViewControllerDelegatei SeparateSecondaryViewController . UINavigationController implementuje te metody w celu automatycznego wypychania i wyskakowania kontrolera widoku pomocniczego.

Wyświetlanie kontrolerów widoku

Kolejną zmianą, którą firma Apple wprowadziła w systemie iOS 8, jest sposób, w jaki deweloper pokazuje kontrolery widoku. W przeszłości, jeśli aplikacja miała kontroler widoku liścia (na przykład kontroler widoku tabeli), a deweloper pokazał inny (na przykład w odpowiedzi na naciśnięcie komórki przez użytkownika), aplikacja wróci przez hierarchię kontrolera do kontrolera widoku nawigacji i wywoła PushViewController metodę względem niej, aby wyświetlić nowy widok.

Przedstawiało to bardzo ścisłe sprzężenie między kontrolerem nawigacji a środowiskiem, w którym był uruchomiony. W systemie iOS 8 firma Apple rozdzieliła to, udostępniając dwie nowe metody:

  • ShowViewController – Dostosowuje się do wyświetlania nowego kontrolera widoku na podstawie jego środowiska. Na przykład w obiekcie UINavigationController po prostu wypycha nowy widok do stosu. W kontrolerze widoku podzielonego nowy kontroler widoku zostanie przedstawiony po lewej stronie jako nowy kontroler widoku podstawowego. Jeśli kontroler widoku kontenera nie jest obecny, nowy widok zostanie wyświetlony jako modalny kontroler widoku.
  • ShowDetailViewController — działa w podobny sposób do ShowViewController, ale jest zaimplementowany na kontrolerze widoku podzielonego, aby zastąpić widok szczegółów nowym kontrolerem widoku przekazywanym. Jeśli kontroler widoku podzielonego jest zwinięty (jak można zobaczyć w aplikacji i Telefon), wywołanie zostanie przekierowane do ShowViewController metody, a nowy widok zostanie wyświetlony jako kontroler widoku podstawowego. Ponownie, jeśli kontroler widoku kontenera nie jest obecny, nowy widok zostanie wyświetlony jako modalny kontroler widoku.

Te metody działają, zaczynając od kontrolera widoku liścia i przechodząc do hierarchii widoków, dopóki nie znajdą odpowiedniego kontrolera widoku kontenera do obsługi wyświetlania nowego widoku.

Deweloperzy mogą implementować ShowViewController i ShowDetailViewController we własnych niestandardowych kontrolerach widoku, aby uzyskać te same funkcje, które UINavigationController i UISplitViewController udostępniają.

Jak to działa

W tej sekcji przyjrzymy się, jak te metody są rzeczywiście implementowane w systemie iOS 8. Najpierw przyjrzyjmy się nowej GetTargetForAction metodzie:

Nowa metoda GetTargetForAction

Ta metoda przeprowadzi łańcuch hierarchii do momentu znalezienia poprawnego kontrolera widoku kontenera. Na przykład:

  1. ShowViewController Jeśli wywoływana jest metoda, pierwszy kontroler widoku w łańcuchu, który implementuje tę metodę, jest kontrolerem nawigacji, więc jest używany jako element nadrzędny nowego widoku.
  2. Jeśli zamiast tego wywołano metodę ShowDetailViewController , kontroler widoku podzielonego jest pierwszym kontrolerem widoku, który go zaimplementował, więc jest używany jako element nadrzędny.

Metoda GetTargetForAction działa, lokalizując kontroler widoku, który implementuje daną akcję, a następnie pytając, czy kontroler widoku ma otrzymać tę akcję. Ponieważ ta metoda jest publiczna, deweloperzy mogą tworzyć własne metody niestandardowe, które działają podobnie jak wbudowane ShowViewController metody i ShowDetailViewController .

Prezentacja adaptacyjna

W systemie iOS 8 firma Apple dokonała również adaptacyjnego pokazu Popover ( UIPopoverPresentationController). Dlatego kontroler widoku prezentacji popover automatycznie przedstawi normalny widok popover w klasie Zwykłego rozmiaru, ale wyświetli pełny ekran w klasie rozmiaru w poziomie (np. na i Telefon).

Aby uwzględnić zmiany w ujednoliconym systemie scenorysów, został utworzony nowy obiekt kontrolera do zarządzania przedstawionymi kontrolerami widoku — UIPresentationController. Ten kontroler jest tworzony na podstawie czasu prezentowania kontrolera widoku do momentu jego odrzucenia. Ponieważ jest to klasa zarządzania, można ją uznać za superklasę nad kontrolerem widoku, ponieważ reaguje na zmiany urządzeń, które mają wpływ na kontroler widoku (np. orientację), które następnie są przekazywane z powrotem do kontrolera widoku kontrolki Kontroler prezentacji.

Gdy deweloper przedstawia kontroler widoku przy użyciu PresentViewController metody , zarządzanie procesem prezentacji jest przekazywane do programu UIKit. Zestaw UIKit obsługuje (między innymi) prawidłowy kontroler dla tworzonego stylu, z jedynym wyjątkiem, gdy kontroler widoku ma ustawiony styl na UIModalPresentationCustom. W tym miejscu aplikacja może podać własny kontroler PresentationController, a nie za pomocą UIKit kontrolera.

Niestandardowe style prezentacji

W przypadku niestandardowego stylu prezentacji deweloperzy mają możliwość używania niestandardowego kontrolera prezentacji. Ten kontroler niestandardowy może służyć do modyfikowania wyglądu i zachowania widoku, do którego jest powiązany.

Praca z klasami rozmiarów

Projekt Xamarin z adaptacyjnymi zdjęciami dołączonymi do tego artykułu zawiera działający przykład użycia klas rozmiarów i kontrolerów widoku adaptacyjnego w aplikacji ujednoliconego interfejsu systemu iOS 8.

Podczas gdy aplikacja tworzy swój interfejs użytkownika całkowicie na podstawie kodu, w przeciwieństwie do tworzenia ujednoliconego scenorysu przy użyciu konstruktora interfejsu Xcode, mają zastosowanie te same techniki.

Teraz przyjrzyjmy się bliżej temu, jak projekt Adaptacyjne zdjęcia implementuje kilka funkcji klasy size w systemie iOS 8 w celu utworzenia aplikacji adaptacyjnej.

Dostosowywanie do zmian w środowisku cech

Podczas uruchamiania aplikacji Adaptacyjne zdjęcia na urządzeniu i Telefon, gdy użytkownik obraca urządzenie z pionowego na poziomy, kontroler widoku podzielonego będzie wyświetlać zarówno widok główny, jak i widok szczegółów:

Kontroler widoku podzielonego wyświetli widok główny i widok szczegółów, jak pokazano tutaj

Jest to realizowane przez zastąpienie UpdateConstraintsForTraitCollection metody kontrolera widoku i dostosowanie ograniczeń na podstawie wartości VerticalSizeClass. Na przykład:

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 ());
}

Dodawanie animacji przejścia

Gdy kontroler widoku podzielonego w aplikacji Adaptacyjne zdjęcia przechodzi od zwiniętego do rozwiniętego, animacje są dodawane do domyślnych animacji przez zastąpienie WillTransitionToTraitCollection metody kontrolera widoku. Na przykład:

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

Zastępowanie środowiska cech

Jak pokazano powyżej, aplikacja Adaptacyjne zdjęcia wymusza, aby kontroler widoku podzielonego wyświetlał zarówno szczegóły, jak i widoki główne, gdy urządzenie i Telefon znajduje się w widoku poziomym.

Wykonano to za pomocą następującego kodu w kontrolerze widoku:

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);
}

Rozszerzanie i zwijanie kontrolera widoku podzielonego

Następnie sprawdźmy, jak rozszerzenie i zwijanie zachowania kontrolera widoku podzielonego zostało zaimplementowane na platformie Xamarin. W programie po utworzeniu AppDelegatekontrolera widoku podzielonego jego pełnomocnik jest przypisany do obsługi tych zmian:

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 ();
    }
}

Metoda SeparateSecondaryViewController sprawdza, czy zdjęcie jest wyświetlane i podejmuje działania na podstawie tego stanu. Jeśli żadne zdjęcie nie jest wyświetlane, zwija kontroler widoku pomocniczego, tak aby kontroler widoku głównego był wyświetlany.

Metoda CollapseSecondViewController jest używana podczas rozszerzania kontrolera widoku podzielonego, aby sprawdzić, czy istnieją jakiekolwiek zdjęcia na stosie, jeśli tak, to zwinie się z powrotem do tego widoku.

Przechodzenie między kontrolerami widoku

Następnie przyjrzyjmy się, jak aplikacja Adaptacyjne zdjęcia przenosi się między kontrolerami widoku. AAPLConversationViewController W klasie, gdy użytkownik wybierze komórkę z tabeli, metoda jest wywoływana w ShowDetailViewController celu wyświetlenia widoku szczegółów:

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);
}

Wyświetlanie wskaźników ujawnienia

W aplikacji Adaptacyjne zdjęcie istnieje kilka miejsc, w których wskaźniki ujawniania są ukryte lub wyświetlane na podstawie zmian w środowisku cech. Jest to obsługiwane za pomocą następującego kodu:

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;
    }
}

Są one implementowane przy użyciu metody omówionej GetTargetViewControllerForAction szczegółowo powyżej.

Gdy kontroler widoku tabeli wyświetla dane, używa metod zaimplementowanych powyżej, aby zobaczyć, czy wypchnięcie ma się zdarzyć, i czy wyświetlić lub ukryć odpowiednio wskaźnik ujawnienia:

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;
}

Nowy ShowDetailTargetDidChangeNotification typ

Firma Apple dodała nowy typ powiadomienia do pracy z klasami rozmiarów i środowiskami cech z poziomu kontrolera widoku podzielonego, ShowDetailTargetDidChangeNotification. To powiadomienie jest wysyłane za każdym razem, gdy docelowy widok szczegółowy dla kontrolera widoku podzielonego zmieni się, na przykład gdy kontroler rozwija się lub zwija.

Aplikacja Adaptacyjne zdjęcia używa tego powiadomienia, aby zaktualizować stan wskaźnika ujawnienia, gdy zmieni się kontroler widoku szczegółów:

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

Przyjrzyj się bliżej aplikacji Adaptacyjne zdjęcia, aby zobaczyć wszystkie sposoby, w jakie klasy rozmiarów, kolekcje cech i kontrolery widoku adaptacyjnego mogą służyć do łatwego tworzenia ujednoliconej aplikacji na platformie Xamarin.iOS.

Ujednolicone scenorysy

Nowość w systemie iOS 8 ujednolicone scenorysy umożliwiają deweloperowi utworzenie jednego, ujednoliconego pliku scenorysu, który może być wyświetlany zarówno na urządzeniach i Telefon, jak i iPad, kierując wiele klas rozmiarów. Korzystając z ujednoliconych scenorysów, deweloper zapisuje mniej kodu specyficznego dla interfejsu użytkownika i ma tylko jeden projekt interfejsu do tworzenia i konserwacji.

Najważniejsze korzyści płynące z ujednoliconych scenorysów to:

  • Użyj tego samego pliku scenorysu dla systemów i Telefon i iPad.
  • Wdrażanie do tyłu w systemach iOS 6 i iOS 7.
  • Wyświetl podgląd układu dla różnych urządzeń, orientacji i wersji systemu operacyjnego .

Włączanie klas rozmiarów

Domyślnie każdy nowy projekt platformy Xamarin.iOS będzie używać klas rozmiarów. Aby użyć klas rozmiarów i segues adaptacyjnych wewnątrz scenorysu ze starszego projektu, należy najpierw przekonwertować go na format Xcode 6 Unified Storyboard, a pole wyboru Użyj klas rozmiarów jest zaznaczone w inspektorze plików Xcode dla scenorysów.

Dynamiczne ekrany uruchamiania

Plik ekranu uruchamiania jest wyświetlany jako ekran powitalny podczas uruchamiania aplikacji systemu iOS w celu przekazania opinii użytkownikowi, że aplikacja rzeczywiście uruchamia się. Przed systemem iOS 8 deweloper musiałby uwzględnić wiele Default.png zasobów obrazów dla każdego typu urządzenia, orientacji i rozdzielczości ekranu, na którym będzie uruchomiona aplikacja. Na przykład , Default@2x.png, Default-Landscape@2x~ipad.png, Default-Portrait@2x~ipad.pngitp.

Faktoring w nowych urządzeniach i Telefon 6 i i Telefon 6 Plus (i nadchodzących urządzeniach Apple Watch) ze wszystkimi istniejącymi urządzeniami i Telefon iPad, reprezentuje dużą tablicę różnych rozmiarów, orientacji i rozdzielczości zasobów obrazów ekranu startowegoDefault.png, które muszą zostać utworzone i utrzymane. Ponadto te pliki mogą być dość duże i będą "wydmuchane" pakiet aplikacji dostarczanych, zwiększając ilość czasu wymaganego do pobrania aplikacji ze sklepu iTunes App Store (ewentualnie uniemożliwienie dostarczenia jej przez sieć komórkową) i zwiększenie ilości miejsca wymaganego na urządzeniu użytkownika końcowego.

Nowy dla systemu iOS 8 deweloper może utworzyć pojedynczy, niepodzielny .xib plik w programie Xcode, który używa klas automatycznego układu i rozmiaru do tworzenia dynamicznego ekranu uruchamiania, który będzie działać dla każdego urządzenia, rozdzielczości i orientacji. Zmniejsza to nie tylko ilość pracy wymaganej przez dewelopera do utworzenia i obsługi wszystkich wymaganych zasobów obrazu, ale znacznie zmniejsza rozmiar zainstalowanego pakietu aplikacji.

Dynamiczne ekrany uruchamiania mają następujące ograniczenia i zagadnienia:

  • Używaj tylko UIKit klas.
  • Użyj pojedynczego widoku głównego, który jest obiektem UIView lub UIViewController .
  • Nie należy nadawać żadnych połączeń z kodem aplikacji (nie dodawaj akcji ani placówek).
  • Nie dodawaj UIWebView obiektów.
  • Nie używaj żadnych klas niestandardowych.
  • Nie używaj atrybutów środowiska uruchomieniowego.

Mając na uwadze powyższe wytyczne, przyjrzyjmy się dodaniu dynamicznego ekranu uruchamiania do istniejącego projektu platformy Xamarin iOS 8.

Należy wykonać następujące czynności:

  1. Otwórz Visual Studio dla komputerów Mac i załaduj rozwiązanie, aby dodać dynamiczny ekran uruchamiania.

  2. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy MainStoryboard.storyboard plik i wybierz polecenie Otwórz za pomocą>narzędzia Xcode Interface Builder:

    Otwórz za pomocą narzędzia Xcode Interface Builder

  3. W programie Xcode wybierz pozycję Plik>nowy>plik...:

    Wybierz pozycję Plik/Nowy

  4. Wybierz ekran uruchamiania interfejsu użytkownika systemu>iOS>i kliknij przycisk Dalej:

    Wybieranie systemu iOS/interfejsu użytkownika/ ekranu uruchamiania

  5. Nadaj plikowi LaunchScreen.xib nazwę i kliknij przycisk Utwórz :

    Nadaj plikowi nazwę LaunchScreen.xib

  6. Edytuj projekt ekranu uruchamiania, dodając elementy graficzne i używając ograniczeń układu, aby ustawić je dla danych urządzeń, orientacji i rozmiarów ekranu:

    Edytowanie projektu ekranu uruchamiania

  7. Zapisz zmiany w pliku LaunchScreen.xib.

  8. Wybierz pozycję Cel aplikacji i kartę Ogólne :

    Wybierz element docelowy aplikacji i kartę Ogólne

  9. Kliknij przycisk Wybierz plik Info.plist, wybierz Info.plist aplikację Xamarin i kliknij przycisk Wybierz:

    Wybierz plik Info.plist dla aplikacji platformy Xamarin

  10. W sekcji Ikony aplikacji i Uruchamianie obrazów otwórz listę rozwijaną Launch Screen File (Uruchom plik osłony uruchamiania) i wybierz LaunchScreen.xib utworzone powyżej:

    Wybierz plik LaunchScreen.xib

  11. Zapisz zmiany w pliku i wróć do Visual Studio dla komputerów Mac.

  12. Poczekaj, aż Visual Studio dla komputerów Mac zakończyć synchronizowanie zmian za pomocą programu Xcode.

  13. W Eksplorator rozwiązań kliknij prawym przyciskiem myszy folder Resource i wybierz polecenie Dodaj>pliki...:

    Wybierz pozycję Dodaj/Dodaj pliki...

  14. LaunchScreen.xib Wybierz utworzony powyżej plik i kliknij przycisk Otwórz:

    Wybierz plik LaunchScreen.xib

  15. Zbuduj aplikację.

Testowanie dynamicznego ekranu uruchamiania

W Visual Studio dla komputerów Mac wybierz symulator i Telefon 4 Siatkówka i uruchom aplikację. Ekran uruchamiania dynamicznego będzie wyświetlany w poprawnym formacie i orientacji:

Ekran uruchamiania dynamicznego wyświetlany w orientacji pionowej

Zatrzymaj aplikację w Visual Studio dla komputerów Mac i wybierz urządzenie z systemem iPad iOS 8. Uruchom aplikację, a ekran uruchamiania zostanie poprawnie sformatowany dla tego urządzenia i orientacji:

Ekran uruchamiania dynamicznego wyświetlany w orientacji poziomej

Wróć do Visual Studio dla komputerów Mac i zatrzymaj działanie aplikacji.

Praca z systemem iOS 7

Aby zachować zgodność z poprzednimi wersjami systemu iOS 7, wystarczy uwzględnić zwykłe Default.png zasoby obrazów w zwykły sposób w aplikacji systemu iOS 8. System iOS powróci do poprzedniego zachowania i użyje tych plików jako ekranu uruchamiania podczas uruchamiania na urządzeniu z systemem iOS 7.

Podsumowanie

W tym artykule przedstawiono szybko klasy rozmiarów i sposób ich wpływu na układ urządzeń i Telefon i iPad. Omówiono w nim sposób pracy cech, środowisk cech i kolekcji cech z klasami rozmiarów w celu utworzenia ujednoliconych interfejsów. Pokrótce przyjrzeliśmy się kontrolerom widoków adaptacyjnych i sposobie pracy z klasami rozmiarów w ujednoliconych interfejsach. Przyjrzeliśmy się implementacji klas rozmiarów i ujednoliconych interfejsów całkowicie z kodu języka C# w aplikacji platformy Xamarin dla systemu iOS 8.

Na koniec w tym artykule opisano podstawy tworzenia pojedynczego dynamicznego ekranu uruchamiania, który będzie wyświetlany jako ekran startowy na każdym urządzeniu z systemem iOS 8.