共用方式為


Xamarin.iOS 中的整合分鏡腳本

iOS 8 包含用於建立使用者介面的新簡單使用機制,也就是統一的分鏡腳本。 使用單一分鏡腳本來涵蓋所有不同的硬體螢幕大小,即可使用「設計一次、多用途」樣式來建立快速且回應式的檢視。

由於開發人員不再需要為 i 電話 和 iPad 裝置建立個別且特定的分鏡腳本,因此他們具有彈性地使用通用介面設計應用程式,然後針對不同的大小類別自定義該介面。 如此一來,應用程式就可以適應每個尺寸的優點,而且可以微調每個使用者介面,以提供最佳的體驗。

大小類別

在 iOS 8 之前,開發人員使用 UIInterfaceOrientationUIInterfaceIdiom 來區分直向和橫向模式,以及 i 電話 和 iPad 裝置。 在 iOS8 中,方向和裝置取決於使用 大小類別

裝置是由大小類別所定義,在垂直軸和水平軸中,iOS 8 中有兩種類型的大小類別:

  • 一般 – 這是針對大型螢幕大小(例如 iPad)或小工具,給大尺寸的印象(例如 UIScrollView
  • Compact – 這是針對較小的裝置(例如 i 電話)。 此大小會考慮裝置的方向。

如果兩個概念一起使用,結果會是 2 x 2 方格,定義可用於兩個不同方向的不同可能大小,如下圖所示:

2 x 2 網格線,定義可用於一般和精簡方向的不同可能大小

開發人員可以建立檢視控制器,其使用四種可能性中的任何一種,會導致不同的版面配置(如上圖所示)。

iPad 大小類別

iPad 由於大小,這兩個方向都有一般類別大小。

iPad 大小類別

i 電話 Size 類別

i 電話 根據裝置的方向有不同的大小類別:

i 電話 大小類別

  • 當裝置處於直向模式時,螢幕會以水準和垂直方式有一個精簡的類別
  • 當裝置處於橫向模式時,螢幕類別會從直向模式反轉。

i 電話 6 Plus Size 類別

在直向方向但橫向不同時,這些大小與先前的 i 電話 相同:

i 電話 6 Plus Size 類別

因為 i 電話 6 Plus 有足夠大的螢幕,所以能夠在橫向模式中擁有一般寬度大小類別。

支援新的螢幕縮放比例

i 電話 6 Plus 使用新的 Retina HD 顯示器,其螢幕縮放比例為 3.0(原始 i 電話 螢幕解析度的三倍)。 若要在這些裝置上提供最佳體驗,請包含專為此螢幕縮放而設計的新藝術品。 在 Xcode 6 和更新版本中,資產目錄可以包含 1x、2x 和 3x 大小的影像;只要新增映像資產,iOS 就會在 i 電話 6 Plus 上執行時選擇正確的資產。

iOS 中的影像載入行為也會辨識 @3x 圖像檔上的後綴。 例如,如果開發人員在應用程式的套件組合中包含影像資產(解析度不同),且檔名如下: MonkeyIcon.pngMonkeyIcon@2x.pngMonkeyIcon@3x.png。 在 i 電話 6 Plus 上MonkeyIcon@3x.png,如果開發人員使用下列程式代碼載入映像,系統會自動使用映像:

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

動態啟動畫面

啟動畫面檔案會顯示為啟動顯示畫面,而 iOS 應用程式正在啟動,以提供意見反應給使用者,指出應用程式實際上是啟動。 在 iOS 8 之前,開發人員必須針對應用程式執行的每個裝置類型、方向和螢幕解析度包含多個 Default.png 影像資產。

iOS 8 的新功能是開發人員可以在 Xcode 中建立單一不可部分完成 .xib 的檔案,該檔案會使用自動配置和大小類別來建立 動態啟動畫面 ,以針對每個裝置、解析度和方向運作。 這不僅可減少開發人員建立和維護所有必要的映像資產所需的工作量,還能減少應用程式已安裝套件組合的大小。

特性

特性是屬性,可用來判斷版面配置在環境變更時如何變更。 它們是由一組屬性( HorizontalSizeClassVerticalSizeClass 為基礎 UIUserInterfaceSizeClass),以及介面成語( UIUserInterfaceIdiom)和顯示比例所組成。

上述所有狀態都會包裝在 Apple 稱為 Trait Collection 的容器中, UITraitCollection它不僅包含屬性,而且包含其值。

特徵環境

特性環境是 iOS 8 中的新介面,能夠傳回下列物件的 Trait 集合:

  • 螢幕 ( UIScreens )。
  • Windows ( UIWindows )。
  • 檢視控制器 ( UIViewController
  • 檢視 ( UIView
  • 簡報控制器 ( UIPresentationController )。

開發人員會使用 Trait Environment 所傳回的 Trait 集合來判斷使用者介面的配置方式。

所有特徵環境都會建立階層,如下圖所示:

特徵環境階層圖

上述每個特性環境的特性集合預設都會從父環境流向子環境。

除了取得目前的 Trait 集合之外,Trait Environment 還有方法 TraitCollectionDidChange ,可以在 View 或 View Controller 子類別中覆寫。 開發人員可以使用此方法修改任何相依於特性的 UI 元素,這些特性變更時。

一般特性集合

本節將涵蓋使用 iOS 8 時,使用者會遇到的典型特性集合類型。

以下是開發人員可能會在 i 上看到的典型特性集合 電話:

屬性
HorizontalSizeClass Compact
VerticalSizeClass 一般
UserInterfaceIdom 手機
DisplayScale 2.0

上述集合代表完整特徵集合,因為它具有其所有特性屬性的值。

也可以有一個特徵集合,遺漏其部分值(蘋果稱之為 未指定):

屬性
HorizontalSizeClass Compact
VerticalSizeClass [未指定]
UserInterfaceIdom [未指定]
DisplayScale [未指定]

不過,一般而言,當開發人員詢問 Trait Environment 是否有其特性集合時,它會傳回如上述範例所示的完整集合。

如果特徵環境(例如檢視或檢視控制器)不在目前的檢視階層內,開發人員可能會取得一或多個特性屬性的未指定值。

如果開發人員使用Apple所提供的其中一個建立方法,例如 UITraitCollection.FromHorizontalSizeClass,來建立新的集合,開發人員也會取得部分限定的 Trait 集合。

可以在多個 Trait 集合上執行的一項作業是將它們彼此比較,這牽涉到在包含另一個特性集合時詢問一個特性集合。 Containment 的意義在於,對於第二個集合中指定的任何特徵,值必須與第一個集合中的值完全相符。

若要測試兩個特性,請使用 Contains 傳入要測試之特性值的方法 UITraitCollection

開發人員可以在程式代碼中手動執行比較,以判斷如何配置檢視或檢視控制器。 不過, UIKit 在內部使用此方法來提供其部分功能,例如,如外觀 Proxy。

外觀 Proxy

外觀 Proxy 是在舊版 iOS 中引進的,可讓開發人員自定義其 Views 的屬性。 它已在 iOS 8 中擴充,以支援特性集合。

外觀 Proxy 現在包含新的方法, AppearanceForTraitCollection這個方法會針對已傳入的指定 Trait 集合傳回新的外觀 Proxy。 開發人員在該外觀 Proxy 上執行的任何自定義,只會對符合指定 Trait 集合的檢視生效。

一般而言,開發人員會將部分指定的 Trait 集合傳遞至 AppearanceForTraitCollection 方法,例如只指定 Compact 的水準大小類別,讓開發人員可以自定義應用程式中水準壓縮的任何檢視。

UIImage

Apple 已將 Trait Collection 新增至 的另一個類別是 UIImage。 在過去,開發人員必須指定@1X和@2x版本的任何點圖圖形資產,它們將包含在應用程式中(例如圖示)。

iOS 8 已擴充,可讓開發人員根據特性集合在映像目錄中包含多個版本的映像。 例如,開發人員可以包含較小的映像,以使用 Compact Trait 類別,以及任何其他集合的完整大小映射。

當類別內使用其中一個 UIImageView 影像時,影像檢視會自動顯示其 Trait 集合的正確映像版本。 如果特徵環境變更(例如使用者將裝置從直向切換為橫向),影像檢視會自動選取新的影像大小以符合新的 Trait 集合,並變更其大小以符合目前顯示的影像版本。

UIImageAsset

Apple 已在 iOS 8 中新增了一個名為 UIImageAsset 的類別,讓開發人員更能控制影像選取。

映射資產會包裝所有不同版本的映像,並允許開發人員要求符合傳入之 Trait 集合的特定映像。 您可以即時從影像資產新增或移除影像。

如需影像資產的詳細資訊,請參閱 Apple 的 UIImageAsset 檔。

結合特性集合

開發人員可以在 Trait Collections 上執行的另一個函式是將兩個加在一起,這會導致合併的集合,其中一個集合中的未指定值會由第二個集合中的指定值所取代。 這是使用 FromTraitsFromCollections 類別的方法完成的 UITraitCollection

如上所述,如果在其中一個 Trait Collections 中未指定任何特性,而且在另一個特性中指定,該值將會設定為指定的版本。 不過,如果指定的指定值有多個版本,則最後一個 Trait 集合中的值將會是所使用的值。

調適型檢視控制器

本節將討論 iOS 檢視和檢視控制器如何採用特性和大小類別的概念,以在開發人員的應用程式中自動更具彈性。

分割檢視控制器

在 iOS 8 中變更最多的檢視控制器類別之一是 類別 UISplitViewController 。 過去,開發人員通常會在應用程式的 iPad 版本上使用分割檢視控制器,然後他們必須針對 i 電話 版本的應用程式提供完全不同的檢視階層版本。

在 iOS 8 中,類別UISplitViewController可在兩個平臺上使用(iPad 和 i 電話),這可讓開發人員建立一個檢視控制器階層,以同時針對 i 電話 和 iPad 運作。

當 i 電話 處於橫向時,分割檢視控制器會並存呈現其檢視,就像在 iPad 上顯示時一樣。

覆寫特性

從父容器到子容器的特徵環境串聯,如下圖所示,在 iPad 上以橫向顯示分割檢視控制器:

橫向 iPad 上的分割檢視控制器

由於 iPad 同時具有水準和垂直方向的一般大小類別,因此分割檢視會顯示主檢視和詳細數據檢視。

在 i 電話,其中 Size 類別以兩個方向壓縮,分割檢視控制器只會顯示詳細數據檢視,如下所示:

分割檢視控制器只會顯示詳細數據檢視

在開發人員想要在 i 電話 橫向顯示主要和詳細數據檢視的應用程式中,開發人員必須插入分割檢視控制器的父容器,並覆寫 Trait 集合。 如下圖所示:

開發人員必須插入分割檢視控制器的父容器,並覆寫 Trait 集合

UIView會設定為分割檢視控制器的父系,而且SetOverrideTraitCollection會在傳入新 Trait 集合且以分割檢視控制器為目標的檢視上呼叫 方法。 新的 Trait 集合會HorizontalSizeClass覆寫 ,並將它設定為 Regular,讓分割檢視控制器在橫向的 i 電話 上同時顯示主檢視和詳細數據檢視。

請注意, VerticalSizeClass 已將 設定為 unspecified,這可讓新的 Trait 集合加入父系上的 Trait 集合,進而產生 Compact VerticalSizeClass 子分割檢視控制器的 。

特徵變更

本節將詳細探討特性集合在特性環境變更時如何轉換。 例如,當裝置從直向旋轉到橫向時。

直向橫向特徵變更概觀

首先,iOS 8 會執行一些設定,以準備進行轉換。 接下來,系統會以動畫顯示轉換狀態。 最後,iOS 8 會清除轉換期間所需的任何暫存狀態。

iOS 8 提供數個回呼,開發人員可用來參與特性變更,如下表所示:

階段 回撥 描述
設定
  • WillTransitionToTraitCollection
  • TraitCollectionDidChange
  • 這個方法會在 Trait Change 的開頭呼叫,然後 Trait 集合設定為新的值。
  • 方法會在 Trait 集合的值變更,但在進行任何動畫之前呼叫。
動畫 WillTransitionToTraitCollection 傳遞至這個方法的轉換協調器具有 AnimateAlongside 屬性,可讓開發人員新增將與默認動畫一起執行的動畫。
清理 WillTransitionToTraitCollection 提供方法,讓開發人員在轉換完成後包含自己的清除程序代碼。

此方法 WillTransitionToTraitCollection 非常適合用來建立檢視控制器以及特性集合變更的動畫效果。 方法 WillTransitionToTraitCollection 僅適用於檢視控制器 ( UIViewController),而不適用於其他特性環境,例如 UIViews

TraitCollectionDidChange非常適合使用 UIView 類別,開發人員想要在特性變更時更新UI。

折疊分割檢視控制器

現在讓我們進一步瞭解分割檢視控制器從兩個數據行折迭到一個數據行檢視時會發生什麼情況。 在這項變更中,有兩個程式需要發生:

  • 根據預設,分割檢視控制器會在折迭發生后,使用主要檢視控制器做為檢視。 開發人員可以覆 GetPrimaryViewControllerForCollapsingSplitViewController 寫 的 UISplitViewControllerDelegate 方法,並提供想要以折迭狀態顯示的任何檢視控制器,來覆寫此行為。
  • 次要檢視控制器必須合併到主要檢視控制器。 一般而言,開發人員不需要對此步驟採取任何動作;分割檢視控制器包含根據硬體裝置自動處理此階段。 不過,在某些情況下,開發人員可能會想要與此變更互動。 CollapseSecondViewController呼叫 的 方法UISplitViewControllerDelegate可讓主要檢視控制器在發生折迭時顯示,而不是詳細數據檢視。

展開分割檢視控制器

現在讓我們進一步瞭解分割檢視控制器從折迭狀態展開時會發生什麼情況。 同樣地,有兩個階段需要執行:

  • 首先,定義新的主要檢視控制器。 根據預設,分割檢視控制器會自動從折迭檢視使用主要檢視控制器。 同樣地,開發人員可以使用的 UISplitViewControllerDelegate 方法來覆寫此行為GetPrimaryViewControllerForExpandingSplitViewController
  • 選擇主要檢視控制器之後,必須重新建立次要檢視控制器。 同樣地,分割檢視控制器包含根據硬體裝置自動處理此階段。 開發人員可以呼叫 SeparateSecondaryViewControllerUISplitViewControllerDelegate 方法來覆寫此行為。

在分割檢視控制器中,主要檢視控制器會藉由實 CollapseSecondViewController 作 的 和 SeparateSecondaryViewController 方法 UISplitViewControllerDelegate,在展開和折疊檢視中扮演一部分。 UINavigationController 會實作這些方法,以自動推送並快顯次要檢視控制器。

顯示檢視控制器

Apple 對 iOS 8 所做的另一項變更,就是開發人員顯示檢視控制器的方式。 在過去,如果應用程式有分葉檢視控制器(例如數據表檢視控制器),而開發人員會顯示不同的檢視控制器(例如,為了回應使用者點選單元格),應用程式會透過控制器階層回到瀏覽檢視控制器,並針對它呼叫 PushViewController 方法來顯示新的檢視。

這在流覽控制器與其執行的環境之間呈現非常緊密的結合。 在 iOS 8 中,Apple 藉由提供兩個新的方法來分離這一點:

  • ShowViewController – 根據環境調整以顯示新的檢視控制器。 例如,在 UINavigationController 中,它只會將新的檢視推送至堆疊。 在分割檢視控制器中,新的檢視控制器會顯示在左側做為新的主要檢視控制器。 如果沒有容器檢視控制器,新檢視就會顯示為強制響應檢視控制器。
  • ShowDetailViewController – 的運作方式 ShowViewController與 類似,但在分割檢視控制器上實作,以將詳細數據檢視取代為傳入的新檢視控制器。 如果分割檢視控制器已折疊(如 i 電話 應用程式中所示),則會將呼叫重新導向至 ShowViewController 方法,而新的檢視會顯示為主要檢視控制器。 同樣地,如果沒有容器檢視控制器存在,新的檢視將會顯示為強制響應檢視控制器。

這些方法的運作方式是從分葉檢視控制器開始,並逐步執行檢視階層,直到他們找到正確的容器檢視控制器來處理新檢視的顯示。

開發人員可以在自己的自定義檢視控制器中實ShowViewController作 和 ShowDetailViewController ,以取得 和 UISplitViewController 提供的相同自動化功能UINavigationController

運作方式

在本節中,我們將探討如何在 iOS 8 中實際實作這些方法。 首先,讓我們看看新的 GetTargetForAction 方法:

新的 GetTargetForAction 方法

此方法會逐步執行階層鏈結,直到找到正確的容器檢視控制器為止。 例如:

  1. 如果呼叫方法,實作這個方法的鏈結中第一個 ShowViewController 檢視控制器是導覽控制器,因此會當做新檢視的父系使用。
  2. ShowDetailViewController如果改為呼叫方法,分割檢視控制器是第一個實作它的檢視控制器,因此會當做父代使用。

方法 GetTargetForAction 的運作方式是尋找實作指定動作的檢視控制器,然後詢問檢視控制器是否要接收該動作。 由於此方法是公用的,因此開發人員可以建立自己的自定義方法,就像內 ShowViewController 建的 和 ShowDetailViewController 方法一樣。

調適型簡報

在 iOS 8 中,蘋果也製作了 Popover 簡報 ( UIPopoverPresentationController) 調適性。 因此,Popover 簡報檢視控制器會自動在一般大小類別中呈現一般的 Popover 檢視,但會在水平精簡的大小類別中顯示全螢幕(例如 i 電話)。

為了配合整合分鏡腳本系統中的變更,已建立新的控制器物件來管理呈現的檢視控制器 - UIPresentationController。 從檢視控制器顯示到關閉為止,就會建立此控制器。 因為它是管理類別,它可以視為檢視控制器上的進階類別,因為它會回應影響檢視控制器的裝置變更(例如方向),然後送回簡報控制器控件的檢視控制器。

當開發人員使用 PresentViewController 方法呈現檢視控制器時,會將簡報程式的管理交給 UIKit。 UIKit 會處理所建立之樣式的正確控制器,唯一例外狀況是檢視控制器的樣式設定為 UIModalPresentationCustom時。 在這裡,應用程式可以提供它自己的 PresentationController,而不是使用 UIKit 控制器。

自定義簡報樣式

使用自定義簡報樣式,開發人員可以選擇使用自定義簡報控制器。 這個自定義控制器可用來修改它所盟結之檢視的外觀和行為。

使用 Size 類別

本文隨附的調適型相片 Xamarin 專案提供在 iOS 8 整合介面應用程式中使用大小類別和調適型檢視控制器的工作範例。

雖然應用程式會從程式代碼完全建立其UI,而不是使用 Xcode 的介面產生器建立整合分鏡腳本,但適用相同的技術。

現在讓我們進一步瞭解調適型相片專案如何在iOS 8中實作數個Size類別功能,以建立調適型應用程式。

適應特徵環境變更

在 i 電話 上執行數據適型相片應用程式時,當使用者將裝置從直向旋轉到橫向時,分割檢視控制器會顯示主要和詳細數據檢視:

分割檢視控制器會顯示主要和詳細數據檢視,如下所示

這是藉由覆寫 UpdateConstraintsForTraitCollection 檢視控制器的 方法,並根據的值 VerticalSizeClass調整條件約束來完成。 例如:

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

新增轉換動畫

當調適型相片應用程式中的分割檢視控制器從折疊到展開時,動畫會覆 WillTransitionToTraitCollection 寫檢視控制器的方法,以新增至默認動畫。 例如:

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

覆寫特徵環境

如上所示,調適型相片應用程式會強制分割檢視控制器在i 電話裝置位於橫向檢視時顯示詳細數據和主要檢視。

這是使用檢視控制器中的下列程式代碼來完成的:

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

展開和折疊分割檢視控制器

接下來,讓我們檢查分割檢視控制器的展開和折迭行為如何在 Xamarin 中實作。 在 中 AppDelegate,建立分割檢視控制器時,會指派其委派來處理這些變更:

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

方法 SeparateSecondaryViewController 會測試是否要顯示相片,並根據該狀態採取動作。 如果未顯示任何相片,則會折迭次要檢視控制器,以便顯示主檢視控制器。

CollapseSecondViewController展開分割檢視控制器時會使用 方法,以查看堆疊上是否有任何相片存在,如果是,則會折迭回該檢視。

在檢視控制器之間移動

接下來,讓我們看看調適型相片應用程式在檢視控制器之間移動的方式。 當使用者從資料表ShowDetailViewController中選取儲存格時,AAPLConversationViewController會在類別中呼叫 方法來顯示詳細資料檢視:

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

顯示洩漏指標

在調適型相片應用程式中,有數個地方會根據特性環境的變更來隱藏或顯示洩漏指標。 這是使用下列程式代碼來處理:

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

這些是使用 GetTargetViewControllerForAction 上述詳細討論的方法來實作。

當數據表檢視控制器顯示數據時,它會使用上述實作的方法來查看推送是否會發生,以及是否要據以顯示或隱藏洩漏指標:

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

ShowDetailTargetDidChangeNotification 類型

Apple 已新增通知類型,以便從分割檢視控制器 ShowDetailTargetDidChangeNotification內使用大小類別和特性環境。 每當分割檢視控制器的目標詳細數據檢視變更時,就會傳送此通知,例如控制器展開或折迭時。

調適型相片應用程式會在詳細檢視控制器變更時,使用此通知來更新洩漏指標的狀態:

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

深入瞭解調適型相片應用程式,以查看大小類別、特性集合和調適型檢視控制器可用來在 Xamarin.iOS 中輕鬆建立整合應用程式的所有方式。

整合的 Storyboard

iOS 8 的全新整合分鏡腳本可讓開發人員建立一個統一的分鏡腳本檔案,其可透過以多個大小類別為目標,同時顯示在 i 電話 和 iPad 裝置上。 藉由使用整合分鏡腳本,開發人員會撰寫較少的 UI 特定程式代碼,而且只有一個介面設計來建立和維護。

整合分鏡腳本的主要優點包括:

  • 針對 i 電話 和 iPad 使用相同的分鏡腳本檔案。
  • 向後部署至 iOS 6 和 iOS 7。
  • 預覽不同裝置、方向和OS版本的版面配置。

啟用大小類別

根據預設,任何新的 Xamarin.iOS 項目都會使用大小類別。 若要從較舊的專案使用分鏡腳本內的 Size Classes 和 Adaptive Segues,必須先轉換成 Xcode 6 整合分鏡腳本格式,然後在腳本的 Xcode 檔案偵測器中選取 [使用大小類別] 複選框。

動態啟動畫面

啟動畫面檔案會顯示為啟動顯示畫面,而 iOS 應用程式正在啟動,以提供意見反應給使用者,指出應用程式實際上是啟動。 在 iOS 8 之前,開發人員必須針對應用程式執行的每個裝置類型、方向和螢幕解析度包含多個 Default.png 影像資產。 例如、 Default@2x.pngDefault-Landscape@2x~ipad.pngDefault-Portrait@2x~ipad.png等。

將新的 i 電話 6 和 i 電話 6 Plus 裝置(以及即將推出的 Apple Watch)納入所有現有的 i 電話 和 iPad 裝置中,這代表必須建立和維護之啟動螢幕圖像資產的各種大小、方向和解析度Default.png的大型數位。 此外,這些檔案可能相當大,而且會「膨脹」可傳送的應用程式套件組合,增加從iTunes App Store 下載應用程式所需的時間量(可能使其無法透過行動數據網路傳遞),並增加終端使用者裝置上所需的儲存空間量。

iOS 8 的新功能是開發人員可以在 Xcode 中建立單一不可部分完成 .xib 的檔案,該檔案會使用自動配置和大小類別來建立 動態啟動畫面 ,以針對每個裝置、解析度和方向運作。 這不僅可減少開發人員建立和維護所有必要的映像資產所需的工作量,而且可大幅減少應用程式已安裝套件組合的大小。

動態啟動畫面具有下列限制和考慮:

  • UIKit 使用類別。
  • 使用為或 UIViewController 物件的單一UIView根檢視。
  • 請勿建立應用程式程式代碼的任何連線(請勿新增 動作輸出)。
  • 不要新增 UIWebView 物件。
  • 請勿使用任何自定義類別。
  • 請勿使用運行時間屬性。

考慮到上述指導方針,讓我們看看將動態啟動畫面新增至現有的 Xamarin iOS 8 專案。

執行下列操作:

  1. 開啟 Visual Studio for Mac 並載入 方案 以新增動態啟動畫面。

  2. 在 方案總管,以滑鼠右鍵按兩下MainStoryboard.storyboard檔案,然後選取 [以>Xcode 介面產生器開啟]:

    使用 Xcode 介面產生器開啟

  3. 在 Xcode 中,選取 [檔案>新>檔案...] :

    選取 [檔案] / [新增]

  4. 選取 [iOS>使用者介面>啟動畫面],然後按下一步: 按鈕:

    選取 [iOS/ 使用者介面/ 啟動畫面]

  5. 將檔案 LaunchScreen.xib 命名為 ,然後按兩下 [ 建立] 按鈕:

    將檔案命名為 LaunchScreen.xib

  6. 新增圖形元素並使用版面配置條件約束來針對指定的裝置、方向和螢幕大小放置啟動畫面的設計:

    編輯啟動畫面的設計

  7. 將變更儲存至 LaunchScreen.xib

  8. 選取 [ 應用程式目標 ] 和 [ 一般 ] 索引標籤:

    選取 [應用程式目標] 和 [一般] 索引標籤

  9. 點選取 XamarinInfo.plist 應用程式的 ,然後按兩下 [選擇] 按鈕:

    選取 Xamarin 應用程式的 Info.plist

  10. 在 [ 應用程式圖示和啟動影像 ] 區段中,開啟 [ 啟動畫面檔案 ] 下拉式清單,然後選擇上述建立的專案 LaunchScreen.xib

    選擇 LaunchScreen.xib

  11. 儲存檔案的變更,並返回 Visual Studio for Mac。

  12. 等候 Visual Studio for Mac 完成與 Xcode 的同步處理變更。

  13. 在 方案總管 中,以滑鼠右鍵按兩下 [資源] 資料夾,然後選取 [新增>檔案...] :

    選取 [新增/ 新增檔案...

  14. 選取上方建立的 LaunchScreen.xib 檔案,然後按下 [ 開啟 ] 按鈕:

    選取 LaunchScreen.xib 檔案

  15. 組建應用程式。

測試動態啟動畫面

在 Visual Studio for Mac 中,選取 i 電話 4 Retina 模擬器並執行應用程式。 動態啟動畫面會以正確的格式和方向顯示:

以垂直方向顯示的動態啟動畫面

在 Visual Studio for Mac 中停止應用程式,然後選取 iPad iOS 8 裝置。 執行應用程式並針對此裝置和方向正確格式化啟動畫面:

以水準方向顯示的動態啟動畫面

返回 Visual Studio for Mac,並停止應用程式執行。

使用 iOS 7

若要維持與 iOS 7 的回溯相容性,請在 iOS 8 應用程式中只包含一般 Default.png 映像資產。 iOS 會返回先前的行為,並在 iOS 7 裝置上執行時,使用這些檔案作為啟動畫面。

摘要

本文快速探討大小類別,以及它們如何影響 i 電話 和 iPad 裝置中的版面配置。 它討論了特性、特性環境和特性集合如何搭配大小類別使用,以建立整合介面。 它簡要探討調適型檢視控制器,以及它們如何在整合介面內使用大小類別。 它探討如何從 Xamarin iOS 8 應用程式內的 C# 程式代碼完全實作大小類別和整合介面。

最後,本文涵蓋建立單一動態啟動畫面的基本概念,該畫面將會在每個iOS 8裝置上顯示為啟動畫面。