Sjednocené scénáře v Xamarin.iOS

iOS 8 obsahuje nový, jednodušší mechanismus pro vytváření uživatelského rozhraní – sjednocenou scénářovou strukturu. S jednou scénářem, která zahrnuje všechny různé velikosti hardwarových obrazovek, je možné rychle a responzivní zobrazení vytvořit ve stylu "design-once, use-many".

Vzhledem k tomu, že vývojář už nepotřebuje vytvořit samostatnou a specifickou scénář pro zařízení s i Telefon a iPadem, mají flexibilitu při návrhu aplikací se společným rozhraním a pak toto rozhraní přizpůsobit pro různé třídy velikostí. Tímto způsobem lze aplikaci přizpůsobit na silné stránky každého faktoru formuláře a každé uživatelské rozhraní je možné ladit tak, aby poskytovalo co nejlepší prostředí.

Třídy velikosti

Před iOSem 8 vývojář používal UIInterfaceOrientation režimy na výšku a na šířku a UIInterfaceIdiom mezi zařízeními i Telefon a iPad. V iOSu8 se orientace a zařízení určují pomocí tříd velikostí.

Zařízení jsou definována třídami velikostí ve svislých i vodorovných osách a existují dva typy tříd velikostí v iOSu 8:

  • Normální – Jedná se o velkou velikost obrazovky (například iPad) nebo miniaplikaci, která dává dojem velké velikosti (například UIScrollView
  • Compact – To je pro menší zařízení (například i Telefon). Tato velikost bere v úvahu orientaci zařízení.

Pokud jsou tyto dva koncepty použity společně, výsledkem je mřížka 2 x 2, která definuje různé možné velikosti, které lze použít v obou rozdílných orientacích, jak je vidět v následujícím diagramu:

Mřížka 2 x 2 definující různé možné velikosti, které lze použít v běžných a kompaktních orientacích

Vývojář může vytvořit kontroler zobrazení, který používá některou ze čtyř možností, které by mohly vést k různým rozložením (jak je vidět na obrázku výše).

Třídy velikostí iPadu

IPad má vzhledem k velikosti běžnou velikost třídy pro obě orientace.

Třídy velikostí iPadu

i Telefon třídy velikostí

I Telefon má různé třídy velikostí na základě orientace zařízení:

i Telefon třídy velikostí

  • Pokud je zařízení v režimu na výšku, má obrazovka kompaktní třídu vodorovně a pravidelně svisle.
  • Když je zařízení v režimu na šířku, třídy obrazovky jsou obráceny z režimu na výšku.

i Telefon třídy velikosti 6 plus

Velikosti jsou stejné jako předchozí i Telefon v orientaci na výšku, ale liší se v orientaci na šířku:

i Telefon třídy velikosti 6 plus

Vzhledem k tomu, že i Telefon 6 Plus má dostatečně velkou obrazovku, je schopen mít běžnou třídu šířky velikosti v režimu na šířku.

Podpora nového měřítka obrazovky

I Telefon 6 Plus používá nový displej Retina HD s faktorem měřítka obrazovky 3,0 (třikrát původní i Telefon rozlišení obrazovky). Pro zajištění co nejlepšího prostředí na těchto zařízeních zahrňte nová umělecká díla navržená pro toto měřítko obrazovky. Katalogy prostředků xcode 6 a vyšší můžou obsahovat obrázky o velikosti 1x, 2x a 3x; jednoduše přidejte nové image assety a iOS zvolí správné prostředky při spuštění na i Telefon 6 Plus.

Chování načítání obrázků v iOSu rozpozná také příponu @3x u souborů obrázků. Pokud například vývojář do sady aplikací zahrne prostředek obrázku (v různých rozlišeních) s následujícími názvy souborů: MonkeyIcon.png, MonkeyIcon@2x.pnga MonkeyIcon@3x.png. Na i Telefon 6 Plus MonkeyIcon@3x.png image se použije automaticky, pokud vývojář načte obrázek pomocí následujícího kódu:

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

Obrazovky s dynamickým spuštěním

Soubor úvodní obrazovky se zobrazí jako úvodní obrazovka, zatímco se aplikace pro iOS spouští, aby uživateli poskytla zpětnou vazbu, že aplikace skutečně spouští. Před iOSem 8 by vývojář musel zahrnout více Default.png prostředků obrázků pro každý typ zařízení, orientaci a rozlišení obrazovky, na kterém by aplikace běžela.

Vývojář s iOSem 8 může v Xcode vytvořit jeden atomický .xib soubor, který pomocí tříd automatického rozložení a velikosti vytvoří obrazovku dynamického spuštění, která bude fungovat pro každé zařízení, rozlišení a orientaci. Tím se nejen sníží množství práce, kterou vývojář potřebuje k vytvoření a údržbě všech požadovaných prostředků image, ale zmenší velikost nainstalované sady aplikací.

Vlastnosti

Vlastnosti jsou vlastnosti, které lze použít k určení toho, jak se rozložení mění při změnách jeho prostředí. Skládají se ze sady vlastností ( HorizontalSizeClass a VerticalSizeClass na UIUserInterfaceSizeClasszákladě ), stejně jako idiom rozhraní ( UIUserInterfaceIdiom) a měřítka zobrazení.

Všechny výše uvedené stavy jsou zabalené do kontejneru, na který Apple odkazuje jako na kolekci vlastností ( UITraitCollection), která obsahuje nejen vlastnosti, ale také jejich hodnoty.

Prostředí vlastností

Prostředí vlastností jsou nové rozhraní v iOS 8 a můžou vrátit kolekci vlastností pro následující objekty:

  • Obrazovky ( UIScreens ).
  • Windows ( UIWindows ).
  • Kontrolery zobrazení ( UIViewController ).
  • Zobrazení ( UIView ).
  • Prezentační kontroler ( UIPresentationController ).

Vývojář používá kolekci vlastností vrácenou prostředím vlastností k určení způsobu stanovení uživatelského rozhraní.

Všechna prostředí vlastností tvoří hierarchii, jak je vidět v následujícím diagramu:

Diagram hierarchie prostředí vlastností

Kolekce vlastností, kterou má každá z výše uvedených prostředí vlastností, bude ve výchozím nastavení probíhat z nadřazeného do podřízeného prostředí.

Kromě získání aktuální kolekce vlastností má prostředí vlastností metodu TraitCollectionDidChange , která se dá přepsat v podtřídách zobrazení nebo kontroleru zobrazení. Vývojář může tuto metodu použít k úpravě některého z prvků uživatelského rozhraní, které závisí na vlastnostech, když se tyto vlastnosti změnily.

Typické kolekce vlastností

Tato část se věnuje typickým typům kolekcí vlastností, se kterými se uživatel setká při práci s iOSem 8.

Následuje typická kolekce vlastností, kterou vývojář může vidět na i Telefon:

Vlastnost Hodnota
HorizontalSizeClass Compact
VerticalSizeClass Regulární
UserInterfaceIdom telefonní
DisplayScale 2.0

Výše uvedená sada by představovala plně kvalifikovanou kolekci vlastností, protože má hodnoty pro všechny její vlastnosti.

Je také možné mít kolekci vlastností, která chybí některé z jejích hodnot (které Apple označuje jako nezadané):

Vlastnost Hodnota
HorizontalSizeClass Compact
VerticalSizeClass Nespecifikované
UserInterfaceIdom Nespecifikované
DisplayScale Nespecifikované

Obecně však platí, že když vývojář požádá prostředí vlastností pro svou kolekci vlastností, vrátí plně kvalifikovanou kolekci, jak je vidět v předchozím příkladu.

Pokud prostředí vlastností (jako zobrazení nebo kontroler zobrazení) není v aktuální hierarchii zobrazení, může vývojář vrátit nezadané hodnoty pro jednu nebo více vlastností vlastností.

Vývojář také získá částečně kvalifikovanou kolekci vlastností, pokud k vytvoření nové kolekce použije některou z metod vytváření, kterou poskytuje Apple, například UITraitCollection.FromHorizontalSizeClass.

Jedna operace, kterou lze provést u více kolekcí vlastností, je porovnávat je navzájem, což zahrnuje dotaz na jednu kolekci vlastností, pokud obsahuje jinou. To znamená, že pro každou vlastnost zadanou ve druhé kolekci musí hodnota přesně odpovídat hodnotě v první kolekci.

K otestování dvou vlastností použijte Contains metodu UITraitCollection předávání hodnoty vlastnosti, která se má testovat.

Vývojář může porovnání provést ručně v kódu a určit, jak rozložení zobrazení nebo kontrolerů zobrazení. UIKit Tuto metodu však interně používá k poskytování některých jeho funkcí, jako například v proxy vzhledu.

Proxy vzhled

Proxy vzhled byl představen v dřívějších verzích iOS, aby vývojáři mohli přizpůsobit vlastnosti svých zobrazení. V iOSu 8 byla rozšířena tak, aby podporovala kolekce vlastností.

Proxy servery vzhledu nyní obsahují novou metodu, AppearanceForTraitCollectionkterá vrací nový proxy vzhled pro danou kolekci vlastností, která byla předána. Všechna přizpůsobení, která vývojář provádí s tímto proxy vzhledem, se projeví pouze na zobrazeních, která odpovídají zadané kolekci vlastností.

Obecně platí, že vývojář předá metodě částečně zadanou kolekci AppearanceForTraitCollection vlastností, například metodu, která právě určila třídu vodorovné velikosti kompaktního formátu, aby mohli přizpůsobit libovolné zobrazení v aplikaci, která je kompaktní vodorovně.

UIImage

Další třídou, ke které Apple přidal Trait Collection, je UIImage. V minulosti musel vývojář zadat @1X a @2x verzi jakéhokoli rastrového grafického prostředku, který bude zahrnout do aplikace (například ikonu).

iOS 8 byl rozšířen tak, aby vývojář mohl zahrnout do katalogu obrázků více verzí na základě kolekce vlastností. Vývojář může například zahrnout menší obrázek pro práci s kompaktní třídou vlastností a obrázkem v plné velikosti pro jakoukoli jinou kolekci.

Pokud se jeden z obrázků používá uvnitř UIImageView třídy, zobrazení obrázku automaticky zobrazí správnou verzi obrázku pro svou kolekci vlastností. Pokud se změní prostředí vlastností (například uživatel, který přepne zařízení z na výšku na šířku), zobrazení obrázků automaticky vybere novou velikost obrázku tak, aby odpovídala nové kolekci vlastností, a změní jeho velikost tak, aby odpovídala aktuální verzi zobrazeného obrázku.

UIImageAsset

Společnost Apple přidala do iOS 8 novou třídu, UIImageAsset která vývojářům umožňuje ještě větší kontrolu nad výběrem obrázků.

Asset image zabalí všechny různé verze image a umožní vývojáři požádat o konkrétní obrázek, který odpovídá předané kolekci vlastností. Obrázky je možné přidat nebo odebrat z assetu obrázku za běhu.

Další informace o prostředcích obrázků najdete v dokumentaci k UIImageAsset společnosti Apple.

Kombinování kolekcí vlastností

Další funkcí, kterou může vývojář provádět s funkcemi Trait Collections, je sečíst dva dohromady, které budou mít za následek kombinovanou kolekci, kde se nezadané hodnoty z jedné kolekce nahradí zadanými hodnotami v druhé. To se provádí pomocí FromTraitsFromCollections metody UITraitCollection třídy.

Jak je uvedeno výše, pokud některá z vlastností není zadána v některé z kolekcí vlastností a je zadána v jiné, hodnota bude nastavena na zadanou verzi. Pokud je však zadáno více verzí dané hodnoty, bude hodnota z poslední kolekce vlastností použitá.

Adaptivní kontrolery zobrazení

Tato část se zabývá podrobnostmi o tom, jak kontrolery zobrazení a zobrazení pro iOS přijaly koncepty tříd vlastností a velikostí, aby byly automaticky adaptivní v aplikacích vývojáře.

Kontroler rozděleného zobrazení

Jednou z tříd kontroleru zobrazení, které se v iOSu UISplitViewController 8 změnily nejvíce, je třída. V minulosti vývojář často používal Split View Controller ve verzi aplikace pro iPad a pak by musel poskytnout zcela jinou verzi hierarchie zobrazení pro i Telefon verzi aplikace.

V iOSu 8 je třída dostupná na obou platformách (iPad i i Telefon), což umožňuje vývojáři vytvořit jednu hierarchii kontroleru zobrazení, UISplitViewController která bude fungovat pro i Telefon iPad.

Když je i Telefon na šířku, bude kontroler rozděleného zobrazení prezentovat zobrazení vedle sebe stejně jako při zobrazení na iPadu.

Přepsání vlastností

Prostředí vlastností se kaskádují z nadřazeného kontejneru až po podřízené kontejnery, jak je znázorněno na následujícím obrázku znázorňující řadič rozděleného zobrazení na iPadu v orientaci na šířku:

Split View Controller na iPadu v orientaci na šířku

Vzhledem k tomu, že iPad má třídu normální velikosti ve vodorovné i svislé orientaci, zobrazí se zobrazení předlohy i podrobností.

Na i Telefon, kde třída velikosti je kompaktní v obou orientacích, zobrazí kontroler rozděleného zobrazení pouze zobrazení podrobností, jak je znázorněno níže:

Kontroler rozděleného zobrazení zobrazuje jenom zobrazení podrobností.

V aplikaci, ve které chce vývojář zobrazit hlavní i podrobné zobrazení na i Telefon orientaci na šířku, musí vývojář vložit nadřazený kontejner pro Split View Controller a přepsat kolekci vlastností. Jak je vidět na obrázku níže:

Vývojář musí vložit nadřazený kontejner pro Split View Controller a přepsat kolekci vlastností.

A UIView je nastavena jako nadřazená prvek Split View Controller a SetOverrideTraitCollection metoda je volána v zobrazení předávání nové Kolekce vlastností a cílí na Split View Controller. Nová kolekce vlastností přepíše HorizontalSizeClassnastavení Regulartak, aby kontroler rozděleného zobrazení zobrazoval hlavní i podrobná zobrazení na i Telefon v orientaci na šířku.

Všimněte si, že VerticalSizeClass byla nastavena na unspecifiedhodnotu , která umožňuje přidání nové kolekce vlastností do kolekce vlastností v nadřazeném objektu, což vede k podřízené Compact VerticalSizeClass kontroleru rozděleného zobrazení.

Změny vlastností

Tato část se podrobně podíváme na to, jak se při změně prostředí vlastností změní kolekce vlastností. Například když se zařízení otočí z na výšku na šířku.

Přehled změn vlastností na výšku na šířku

Za prvé, iOS 8 provede určitou přípravu na provedení přechodu. V dalším kroku systém animuje stav přechodu. IOS 8 nakonec vyčistí všechny dočasné stavy potřebné během přechodu.

iOS 8 poskytuje několik zpětných volání, které může vývojář použít k účasti na změně vlastností, jak je vidět v následující tabulce:

Fáze Zpětné volání Popis
Nastavení
  • WillTransitionToTraitCollection
  • TraitCollectionDidChange
  • Tato metoda se volá na začátku změny vlastností předtím, než se kolekce vlastností nastaví na její novou hodnotu.
  • Metoda se volá, když se hodnota kolekce trait změnila, ale před provedením jakékoli animace.
Animace WillTransitionToTraitCollection Transition Coordinator, který se předá této metodě, má AnimateAlongside vlastnost, která umožňuje vývojáři přidat animace, které se spustí spolu s výchozími animacemi.
Vyčištění WillTransitionToTraitCollection Poskytuje metodu, jak vývojáři po provedení přechodu zahrnout vlastní kód pro vyčištění.

Tato WillTransitionToTraitCollection metoda je skvělá pro animování kontrolerů zobrazení spolu se změnami kolekce vlastností. Metoda WillTransitionToTraitCollection je k dispozici pouze na View Controllers ( UIViewController) a ne v jiných prostředích vlastností, například UIViews.

To TraitCollectionDidChange je skvělé pro práci s UIView třídou, kde vývojář chce aktualizovat uživatelské rozhraní, protože se vlastnosti mění.

Sbalení kontrolerů rozděleného zobrazení

Teď se podrobněji podíváme na to, co se stane, když se kontroler rozděleného zobrazení sbalí ze dvou sloupců do zobrazení jednoho sloupce. V rámci této změny je potřeba provést dva procesy:

  • Ve výchozím nastavení bude řadič rozděleného zobrazení používat primární kontroler zobrazení jako zobrazení po sbalení. Vývojář může toto chování přepsat přepsáním GetPrimaryViewControllerForCollapsingSplitViewController metody a poskytnutím libovolného UISplitViewControllerDelegate kontroleru zobrazení, který chce zobrazit ve sbaleném stavu.
  • Sekundární kontroler zobrazení se musí sloučit do primárního kontroleru zobrazení. Obecně platí, že vývojář nebude pro tento krok muset provést žádnou akci; Split View Controller zahrnuje automatické zpracování této fáze na základě hardwarového zařízení. Může však existovat několik zvláštních případů, kdy vývojář bude chtít s touto změnou pracovat. CollapseSecondViewController Volání metody UISplitViewControllerDelegate umožňuje, aby se hlavní kontroler zobrazení zobrazoval, když dojde ke sbalení, místo zobrazení podrobností.

Rozbalení kontroleru rozděleného zobrazení

Teď se podrobněji podíváme na to, co se stane, když se řadič rozděleného zobrazení rozbalí z sbaleného stavu. Opět existují dvě fáze, které je potřeba provést:

  • Nejprve definujte nový primární kontroler zobrazení. Ve výchozím nastavení bude řadič rozděleného zobrazení automaticky používat primární kontroler zobrazení z sbaleného zobrazení. Znovu, vývojář může toto chování přepsat pomocí GetPrimaryViewControllerForExpandingSplitViewController metody UISplitViewControllerDelegate .
  • Po zvolení primárního kontroleru zobrazení je nutné znovu vytvořit sekundární kontroler zobrazení. Řadič rozděleného zobrazení opět zahrnuje automatické zpracování této fáze na základě hardwarového zařízení. Vývojář může toto chování přepsat voláním SeparateSecondaryViewController metody UISplitViewControllerDelegate .

V rozděleném zobrazení kontroleru hraje primární kontroler zobrazení roli v rozbalení i sbalení zobrazení implementací CollapseSecondViewController a SeparateSecondaryViewController metod UISplitViewControllerDelegate. UINavigationController implementuje tyto metody pro automatické nasdílení a otevření kontroleru sekundárního zobrazení.

Zobrazení kontrolerů

Další změnou, kterou apple provedl v iOSu 8, je způsob, jakým vývojář zobrazuje kontrolery zobrazení. V minulosti, pokud aplikace měla řadič zobrazení list (například řadič zobrazení tabulky) a vývojář ukázal jiný (například v reakci na uživatele klepnutím na buňku), aplikace by se dostala zpět přes hierarchii kontroleru zobrazení navigace do kontroleru navigačního zobrazení a zavolá metodu PushViewController proti ní, aby se zobrazilo nové zobrazení.

To představovalo velmi úzkou vazbu mezi navigačním kontrolerem a prostředím, ve kterém byl spuštěn. V iOSu 8 společnost Apple tuto možnost oddělila tím, že poskytuje dvě nové metody:

  • ShowViewController – Přizpůsobí se zobrazení nového kontroleru zobrazení na základě jeho prostředí. Například v UINavigationController něm jednoduše nasdílí nové zobrazení do zásobníku. V řadiči rozděleného zobrazení se nový kontroler zobrazení zobrazí na levé straně jako nový primární kontroler zobrazení. Pokud neexistuje žádný kontroler zobrazení kontejneru, nové zobrazení se zobrazí jako modální kontroler zobrazení.
  • ShowDetailViewController – Funguje podobně jako ShowViewController, ale je implementována na Split View Controller nahradit zobrazení podrobností novým kontrolerem zobrazení, který se předává. Pokud je kontroler rozděleného zobrazení sbalený (jak je vidět v aplikaci i Telefon), volání bude přesměrováno na metodu ShowViewController a nové zobrazení se zobrazí jako primární kontroler zobrazení. Opět platí, že pokud není k dispozici žádný kontroler zobrazení kontejneru, nové zobrazení se zobrazí jako modální kontroler zobrazení.

Tyto metody fungují tak, že začínají na řadiči zobrazení List a prochází hierarchii zobrazení, dokud nenajde správný kontroler zobrazení kontejneru pro zpracování zobrazení nového zobrazení.

Vývojáři můžou implementovat a ShowDetailViewController používat ShowViewController vlastní kontrolery zobrazení, aby získali stejné automatizované funkce, které UINavigationController a UISplitViewController poskytuje.

Jak to funguje

V této části se podíváme na to, jak se tyto metody ve skutečnosti implementují v iOSu 8. Nejprve se podíváme na novou GetTargetForAction metodu:

Nová metoda GetTargetForAction

Tato metoda provede řetěz hierarchie, dokud se nenajde správný kontroler zobrazení kontejneru. Příklad:

  1. ShowViewController Pokud je volána metoda, první View Controller v řetězu, který implementuje tuto metodu, je navigační kontroler, takže se používá jako nadřazený prvek nového zobrazení.
  2. ShowDetailViewController Pokud byla volána metoda místo toho, Split View Controller je první view controller k implementaci, takže se používá jako nadřazený.

Metoda GetTargetForAction funguje vyhledáním kontroleru zobrazení, který implementuje danou akci, a poté se zeptá, zda kontroler zobrazení chce tuto akci přijmout. Vzhledem k tomu, že je tato metoda veřejná, můžou vývojáři vytvářet vlastní metody, které fungují stejně jako integrované ShowViewController metody a ShowDetailViewController metody.

Adaptivní prezentace

V iOSu 8 společnost Apple vytvořila také adaptivní překryvné prezentace ( UIPopoverPresentationController). Kontroler překryvného zobrazení prezentace tedy automaticky zobrazí normální zobrazení překryvného okna ve třídě normální velikosti, ale zobrazí ho na celé obrazovce v vodorovně kompaktní třídě velikosti (například na i Telefon).

Aby bylo možné přizpůsobit změny v rámci sjednoceného systému scénářů, byl vytvořen nový objekt kontroleru pro správu prezentovaných kontrolerů - UIPresentationController. Tento kontroler se vytvoří od okamžiku, kdy se kontroler zobrazení zobrazí, dokud se nespustí. Protože se jedná o třídu správy, může být považována za super třídu nad kontrolerem zobrazení, protože reaguje na změny zařízení, které ovlivňují kontroler zobrazení (například orientaci), které se pak vrací zpět do kontroleru zobrazení ovládacích prvků Prezentační kontroler.

Když vývojář předloží kontroler zobrazení pomocí PresentViewController metody, správa procesu prezentace je předána UIKit. UIKit zpracovává (mimo jiné) správný kontroler pro styl, který se vytváří, a jedinou výjimkou je, když má kontroler zobrazení nastavený UIModalPresentationCustomstyl . Aplikace zde může poskytnout vlastní PresentationController místo použití UIKit kontroleru.

Vlastní styly prezentací

S vlastním stylem prezentace mají vývojáři možnost použít vlastní prezentační kontroler. Tento vlastní kontroler lze použít ke změně vzhledu a chování zobrazení, na které je spojen.

Práce s třídami velikosti

Projekt Adaptivní fotografie Xamarin, který je součástí tohoto článku, poskytuje funkční příklad použití tříd velikostí a adaptivních kontrolerů zobrazení v aplikaci sjednoceného rozhraní iOS 8.

Zatímco aplikace vytváří své uživatelské rozhraní zcela z kódu, na rozdíl od vytvoření Sjednocené scénáře pomocí Tvůrce rozhraní Xcode, platí stejné techniky.

Teď se podrobněji podíváme na to, jak projekt Adaptivní fotky implementuje několik funkcí třídy velikostí v iOSu 8, abychom vytvořili adaptivní aplikaci.

Přizpůsobení změnám prostředí vlastností

Při spuštění aplikace Adaptivní fotky na i Telefon, když uživatel otočí zařízení z na výšku na šířku, zobrazí kontroler rozděleného zobrazení hlavní i podrobné zobrazení:

Kontroler rozděleného zobrazení zobrazí hlavní zobrazení i zobrazení podrobností, jak je vidět zde.

To se provádí přepsáním UpdateConstraintsForTraitCollection metody View Controller a úpravou omezení na základě hodnoty VerticalSizeClass. Příklad:

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

Přidání přechodových animací

Když split view Controller in the Adaptive Photos application goes from collapsed to expanded, animations are added to the default animations by přepsáním WillTransitionToTraitCollection metody kontroleru zobrazení. Příklad:

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

Přepsání prostředí vlastností

Jak je vidět výše, aplikace Adaptivní fotografie vynutí Split View Controller zobrazit jak podrobnosti, tak hlavní zobrazení, když i Telefon zařízení je v zobrazení na šířku.

Toho bylo dosaženo pomocí následujícího kódu v kontroleru zobrazení:

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

Rozbalení a sbalení kontroleru rozděleného zobrazení

Teď se podíváme, jak bylo v Xamarinu implementováno rozbalené a sbalené chování kontroleru rozděleného zobrazení. AppDelegatePři vytvoření kontroleru rozděleného zobrazení je jeho delegát přiřazen ke zpracování těchto změn:

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 testuje, jestli se zobrazuje fotka, a provede akci na základě tohoto stavu. Pokud se nezobrazuje žádná fotka, sbalí sekundární kontroler zobrazení tak, aby se zobrazil hlavní kontroler zobrazení.

Metoda CollapseSecondViewController se používá při rozbalení Split View Controller zjistit, jestli v zásobníku existují nějaké fotky, pokud ano, sbalí zpět do tohoto zobrazení.

Přechod mezi kontrolery zobrazení

V dalším kroku se podíváme na to, jak se aplikace Adaptivní fotky pohybuje mezi řadiči zobrazení. AAPLConversationViewController Ve třídě, když uživatel vybere buňku z tabulky, ShowDetailViewController je volána metoda pro zobrazení podrobností:

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

Zobrazení indikátorů zpřístupnění

V aplikaci Adaptivní fotografie existuje několik míst, kde jsou indikátory zpřístupnění skryté nebo zobrazené na základě změn v prostředí vlastností. To se zpracovává pomocí následujícího kódu:

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

Implementují se pomocí GetTargetViewControllerForAction metody popsané výše.

Když kontroler zobrazení tabulky zobrazuje data, pomocí výše implementovaných metod zjistí, jestli dojde k nasdílení změn a jestli se má indikátor zpřístupnění zobrazit nebo skrýt odpovídajícím způsobem:

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

Nový ShowDetailTargetDidChangeNotification typ

Apple přidal nový typ oznámení pro práci s třídami velikostí a prostředími vlastností v rámci split view controller, ShowDetailTargetDidChangeNotification. Toto oznámení se odešle při každé změně cílového zobrazení podrobností pro kontroler rozděleného zobrazení, například při rozbalení nebo sbalení kontroleru.

Aplikace Adaptivní fotografie používá toto oznámení k aktualizaci stavu indikátoru zpřístupnění, když se změní kontroler zobrazení podrobností:

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

Podívejte se podrobněji na aplikaci Adaptivní fotografie a podívejte se na všechny způsoby, jak lze třídy velikostí, kolekce vlastností a kontrolery adaptivního zobrazení použít k snadnému vytvoření sjednocené aplikace v Xamarin.iOS.

Sjednocené scénáře

Nové v iOSu 8 umožňují vývojářům vytvořit jeden jednotný soubor storyboardu, který se dá zobrazit na zařízeních s i Telefon i iPad tím, že cílí na více tříd velikostí. Vývojář pomocí sjednocených scénářů zapisuje méně specifický kód uživatelského rozhraní a má pouze jeden návrh rozhraní pro vytváření a údržbu.

Mezi klíčové výhody jednotných scénářů patří:

  • Použijte stejný soubor scénáře pro i Telefon a iPad.
  • Nasaďte zpět do iOS 6 a iOS 7.
  • Zobrazte náhled rozložení pro různá zařízení, orientace a verze operačního systému .

Povolení tříd velikostí

Ve výchozím nastavení budou všechny nové projekty Xamarin.iOS používat třídy velikostí. Chcete-li použít třídy velikostí a adaptivní segues uvnitř scénáře ze staršího projektu, musí být nejprve převedena do formátu Unified Storyboard Xcode 6 a políčko Použít třídy velikostí je zaškrtnuté v kontrole souborů Xcode pro scénáře.

Obrazovky s dynamickým spuštěním

Soubor úvodní obrazovky se zobrazí jako úvodní obrazovka, zatímco se aplikace pro iOS spouští, aby uživateli poskytla zpětnou vazbu, že aplikace skutečně spouští. Před iOSem 8 by vývojář musel zahrnout více Default.png prostředků obrázků pro každý typ zařízení, orientaci a rozlišení obrazovky, na kterém by aplikace běžela. Například , Default@2x.png, Default-Landscape@2x~ipad.png, Default-Portrait@2x~ipad.pngatd.

Faktoring v nových zařízeních i Telefon 6 a i Telefon 6 Plus (a nadcházejících Apple Watch) se všemi existujícími zařízeními i Telefon a iPad představuje velkou řadu různých velikostí, orientací a rozlišení Default.png prostředků obrázků po spuštění obrazovky, které je potřeba vytvořit a udržovat. Kromě toho mohou být tyto soubory poměrně velké a "bloudí" sada dodávek aplikace, což zvyšuje dobu potřebnou ke stažení aplikace z iTunes App Storu (pravděpodobně ji bude možné doručit přes mobilní síť) a zvýší množství úložiště požadovaného na zařízení koncového uživatele.

Vývojář s iOSem 8 může v Xcode vytvořit jeden atomický .xib soubor, který pomocí tříd automatického rozložení a velikosti vytvoří obrazovku dynamického spuštění, která bude fungovat pro každé zařízení, rozlišení a orientaci. Tím se nejen sníží množství práce potřebné pro vývojáře k vytvoření a údržbě všech požadovaných prostředků image, ale výrazně se zmenší velikost nainstalované sady aplikací.

Obrazovky dynamického spouštění mají následující omezení a důležité informace:

  • Používejte pouze UIKit třídy.
  • Použijte jedno kořenové zobrazení, které je objektemUIView.UIViewController
  • Nepřidávejte žádná připojení k kódu aplikace (nepřidávejte akce ani výstupy).
  • Nepřidávejte UIWebView objekty.
  • Nepoužívejte žádné vlastní třídy.
  • Nepoužívejte atributy modulu runtime.

S ohledem na výše uvedené pokyny se podíváme na přidání dynamické obrazovky pro spuštění do existujícího projektu Xamarin iOS 8.

Postupujte následovně:

  1. Otevřete Visual Studio pro Mac a načtěte řešení, do které chcete přidat dynamickou obrazovku pro spuštění.

  2. V Průzkumník řešení klikněte pravým tlačítkem myši na MainStoryboard.storyboard soubor a vyberte Otevřít v>nástroji Xcode Interface Builder:

    Otevřít v tvůrci rozhraní Xcode

  3. V Xcode vyberte Soubor>nový>soubor...:

    Vybrat soubor / Nový

  4. Vyberte obrazovkuPro spuštění uživatelského rozhraní>iOS>a klikněte na tlačítko Další:

    Výběr iOSu / uživatelského rozhraní / spouštěcí obrazovka

  5. Pojmenujte soubor LaunchScreen.xib a klikněte na tlačítko Vytvořit :

    Pojmenujte soubor LaunchScreen.xib.

  6. Upravte návrh úvodní obrazovky přidáním grafických prvků a použitím omezení rozložení k jejich umístění pro daná zařízení, orientace a velikosti obrazovky:

    Úprava návrhu úvodní obrazovky

  7. Uložte změny do LaunchScreen.xibsouboru .

  8. Vyberte cíl aplikací a kartu Obecné:

    Vyberte cíl aplikací a kartu Obecné.

  9. Klikněte na tlačítko Zvolit info.plist , vyberte Info.plist pro aplikaci Xamarin a klikněte na tlačítko Zvolit :

    Vyberte soubor Info.plist pro aplikaci Xamarin.

  10. V části Ikony aplikací a Spustit obrázky otevřete rozevírací seznam Spustit soubor obrazovky a zvolte LaunchScreen.xib výše vytvořené:

    Zvolte LaunchScreen.xib.

  11. Uložte změny souboru a vraťte se do Visual Studio pro Mac.

  12. Počkejte, až Visual Studio pro Mac dokončí synchronizaci změn pomocí Xcode.

  13. V Průzkumník řešení klikněte pravým tlačítkem na složku Prostředek a vyberte Přidat>soubory...:

    Vyberte Přidat nebo přidat soubory...

  14. LaunchScreen.xib Vyberte soubor vytvořený výše a klikněte na tlačítko Otevřít:

    Výběr souboru LaunchScreen.xib

  15. Sestavení aplikace.

Testování obrazovky dynamického spuštění

V Visual Studio pro Mac vyberte simulátor i Telefon 4 Retina a spusťte aplikaci. Obrazovka dynamického spuštění se zobrazí ve správném formátu a orientaci:

Obrazovka dynamického spuštění zobrazená ve svislé orientaci

Zastavte aplikaci v Visual Studio pro Mac a vyberte zařízení s iPadem iOS 8. Spusťte aplikaci a úvodní obrazovka bude správně naformátovaná pro toto zařízení a orientaci:

Obrazovka dynamického spuštění zobrazená ve vodorovné orientaci

Vraťte se do Visual Studio pro Mac a zastavte spuštění aplikace.

Práce s iOSem 7

Pokud chcete zachovat zpětnou kompatibilitu s iOSem 7, stačí do aplikace pro iOS 8 zahrnout obvyklé Default.png prostředky obrázků jako normální. iOS se vrátí k předchozímu chování a při spuštění na zařízení s iOSem 7 použije tyto soubory jako úvodní obrazovku.

Shrnutí

Tento článek se rychle podíval na třídy velikostí a na to, jak ovlivňují rozložení v zařízeních s i Telefon a iPadem. Popisuje, jak vlastnosti, prostředí vlastností a kolekce vlastností fungují s třídami velikostí pro vytváření sjednocených rozhraní. Krátce se podívali na kontrolery adaptivního zobrazení a na to, jak fungují s třídami velikostí v rámci sjednocených rozhraní. Podívala se na implementaci tříd velikostí a sjednocených rozhraní zcela z kódu jazyka C# v aplikaci Xamarin iOS 8.

Nakonec se tento článek zabýval základy vytváření jedné dynamické spouštěcí obrazovky, která se zobrazí jako úvodní obrazovka na každém zařízení s iOSem 8.