Windows 10 特刊 2015

第 30 卷,第 11 期

本文章是由機器翻譯。

UI 設計 - Windows 10 的彈性應用程式

Clint Rutkas |Windows 2015

與通用 Windows 平台 (UWP) Windows 10 中,應用程式可以立即在各種裝置系列上執行並自動調整跨不同的螢幕和支援的平台控制項的視窗大小。這些裝置系列如何支援使用者與您的應用程式的互動和如何執行您的應用程式回應並適應執行所在的裝置嗎? 我們將探討這以及工具和資源 Microsoft 提供在平台,所以您不需撰寫和維護複雜的程式碼執行跨不同裝置類型的應用程式。

首先您可用來最佳化不同裝置系列的 UI 回應性技術的探索。然後我們會深入到您的應用程式可以適用於特定裝置功能的方式。

我們深入控制項、 Api 和程式碼之前,讓我們先花點時間來瀏覽我們的意思了裝置系列。簡單的說: 裝置系列是一組特定的外型規格,範圍從 IoT 裝置、 智慧型手機、 平板電腦和桌上型電腦遷移到 Xbox 遊戲主控台、 大螢幕介面中樞裝置以及甚至 wearables 的裝置。應用程式可跨所有這些裝置系列,但請務必考慮它可以用來設計您的應用程式時的裝置系列。

雖然還有許多裝置系列,UWP 的設計可讓 85%的 Api 都完全可存取任何應用程式、 獨立的執行位置。除此之外時查看排名前 1000 個應用程式,96.2 百分之用的所有 Api 都可兼顧通用 Windows 應用程式開發介面設定基底。大量是功能的存在並可使用特殊 Api 可用來進一步每台裝置上的 UWP 一部分量身訂做您的應用程式。

歡迎回來 Windows

最大的變更應用程式在 Windows 中的使用方式的其中一個是您已經非常熟悉: 在視窗中執行應用程式。Windows 8 和 Windows 8.1 允許同時最多四個應用程式與執行全螢幕或由並行的應用程式。Windows 10 相較之下,讓使用者可以排列、 大小和位置的應用程式中任何他想要的方式。Windows 10 底下的新方法可讓使用者更好 UI 彈性,但可能需要一些在您針對它進行最佳化的端上運作。改進 Windows 10 在 XAML 中的介紹數種方法可以實作應用程式中的回應速度快的技術讓它看起來很棒不論螢幕或視窗大小。讓我們來探索三種方法。

VisualStateManager 中 Windows 10 VisualStateManager 類別已經擴充兩個機制在您以 XAML 為基礎的應用程式中實作的回應式設計。新的 VisualState.StateTriggers 和 VisualState.Setters Api 可讓您定義視覺狀態對應至特定條件。視覺狀態可以變更為 VisualState StateTrigger 使用內建 AdaptiveTrigger 並設定 MinWindowHeight 和 MinWindowWidth 屬性根據應用程式視窗的高度和寬度。您也可以擴充 Windows.UI.Xaml.StateTriggerBase 建立您自己觸發程序、 觸發入裝置家族的執行個體或輸入型別。看看中的程式碼 [圖 1

[圖 1 建立的自訂狀態觸發程序

<Page>
  <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <VisualStateManager.VisualStateGroups>
      <VisualStateGroup>
        <VisualState>
          <VisualState.StateTriggers>
          <!-- VisualState to be triggered when window
            width is >=720 effective pixels. -->
            <AdaptiveTrigger MinWindowWidth="720" />
          </VisualState.StateTriggers>
          <VisualState.Setters>
            <Setter Target="myPanel.Orientation"
                    Value="Horizontal" />
          </VisualState.Setters>
        </VisualState>
      </VisualStateGroup>
    </VisualStateManager.VisualStateGroups>
    <StackPanel x:Name="myPanel" Orientation="Vertical">
      <TextBlock Text="This is a block of text. It is text block 1. "
                 Style="{ThemeResource BodyTextBlockStyle}"/>
      <TextBlock Text="This is a block of text. It is text block 2. "
                 Style="{ThemeResource BodyTextBlockStyle}"/>
      <TextBlock Text="This is a block of text. It is text block 3. "
                 Style="{ThemeResource BodyTextBlockStyle}"/>
    </StackPanel>
  </Grid>
</Page>

在範例中 [圖 1, ,頁面會顯示三個 TextBlock 項目堆疊在彼此的上層為預設狀態。VisualStateManager 已定義在 MinWindowWidth 720,這會導致 StackPanel 視窗時至少 720 有效像素寬變更為水平方向 AdaptiveTrigger。這可讓您進行的額外水平的螢幕面積調整視窗大小或從直式移至橫向模式電話或平板電腦裝置上的使用者時使用。請記住,如果您定義的寬度和高度屬性、 觸發程序才會觸發應用程式同時符合兩個條件。您可以在 GitHub 上探索狀態觸發程序範例 (wndw.ms/XUneob) 若要檢視更多的案例使用觸發程序,包括自訂觸發程序的數目。

相對面板[圖 1 例如 StateTrigger 用來變更 StackPanel [方向] 屬性。在 XAML 中,結合 StateTriggers,許多的容器項目可讓您操作方式,一大堆 UI,但它們不提供輕鬆建立複雜且反應快的 UI 項目彼此相對的配置位置的方式。這是新 RelativePanel 會傳入。中所示 [圖 2, ,您可以使用 RelativePanel 來安排您的項目表示空間項目之間的關聯性。這表示您輕鬆地可以使用與 AdaptiveTriggers RelativePanel 建立反應迅速的 UI,您將根據可用的螢幕空間的項目。

[圖 2 Express RelativePanel 空間關聯性

<RelativePanel BorderBrush="Gray" BorderThickness="10">
  <Rectangle x:Name="RedRect" Fill="Red" MinHeight="100" MinWidth="100"/>
  <Rectangle x:Name="BlueRect" Fill="Blue" MinHeight="100" MinWidth="100"
             RelativePanel.RightOf="RedRect" />
  <!-- Width is not set on the green and yellow rectangles.
       It's determined by the RelativePanel properties. -->
  <Rectangle x:Name="GreenRect" Fill="Green"
             MinHeight="100" Margin="0,5,0,0"
             RelativePanel.Below="RedRect"
             RelativePanel.AlignLeftWith="RedRect"
             RelativePanel.AlignRightWith="BlueRect"/>
  <Rectangle Fill="Yellow" MinHeight="100"
             RelativePanel.Below="GreenRect"
             RelativePanel.AlignLeftWith="BlueRect"
             RelativePanel.AlignRightWithPanel="True"/>
</RelativePanel>

提醒您,使用附加屬性的語法包含額外的括號,如下所示:

<VisualStateManager.VisualStateGroups>
  <VisualStateGroup>
    <VisualState>
      <VisualState.StateTriggers>
        <AdaptiveTrigger MinWindowWidth="720" />
      </VisualState.StateTriggers>
      <VisualState.Setters>
        <Setter Target="GreenRect.(RelativePanel.RightOf)"
                Value="BlueRect" />
      </VisualState.Setters>
    </VisualState>

您可以看看其他案例在 GitHub 上的回應性技術範例中使用 RelativePanel (wndw.ms/cbdL0q)。

SplitView 應用程式頁面上顯示的應用程式視窗大小會影響多個內容 ; 它可能需要導覽元素因應變更視窗本身的大小。Windows 10 中導入新的 SplitView 控制項通常用來建立可調整的作業方式根據應用程式視窗的大小的最上層的巡覽經驗。請記住雖然這是一個 SplitView 的常見使用案例,但不是嚴格限制此用途。SplitView 分成兩個不同區域: 窗格和內容。

在控制項上的屬性數目可以用於管理簡報。首先,DisplayMode 指定窗格相對於具有四個可用的模式的內容區域的呈現方式 — 內嵌、 CompactOverlay 和 CompactInline 重疊。[圖 3 顯示在應用程式中呈現的內嵌、 重疊及 CompactInline 模式的範例。

DisplayMode 巡覽項目
[圖 3 DisplayMode 巡覽項目

PanePlacement 屬性顯示窗格左邊 (預設值) 或內容區域的右側。OpenPaneLength 屬性指定窗格的寬度時它已完全擴展 (預設 320 有效像素)。

請注意 SplitView 控制項不包含內建的 UI 項目讓使用者切換] 窗格中,像是一般的"漢堡"功能表經常會出現在行動應用程式的狀態。如果您想要公開此行為,您必須在您的應用程式中定義此 UI 項目並提供切換 SplitView IsPaneOpen 屬性的程式碼。

想要探索整組 SplitView 提供的功能嗎? 請務必查看 GitHub 上的 XAML 瀏覽功能表範例 (wndw.ms/qAUVr9)。

將 [上一頁] 按鈕

如果您開發適用於舊版的 Windows Phone 應用程式,您可能會習慣於擁有硬體或軟體的上一頁按鈕,每個裝置可讓使用者巡覽回透過您的應用程式。Windows 8 和 8.1,不過,必須建立的向後巡覽 UI。為了方便目標為 Windows 10 應用程式中的多個裝置系列時,沒有方法可確保所有使用者的一致後導覽機制。這有助於釋出往後的應用程式中的某些 UI 空間。

若要啟用系統應用程式中,即使在沒有任何硬體或軟體的上一頁按鈕 (例如膝上型電腦和桌上型電腦 Pc) 的裝置系列上一步] 按鈕會使用 AppViewBackButtonVisibility 屬性 SystemNavigationManager 類別中。只要 SystemNavigationManager 取得目前的檢視和設定一步] 按鈕的可見性的下列程式碼所示:

SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility =
  AppViewBackButtonVisibility.Visible;

SystemNavigationManager 類別也會公開一個 BackRequested 事件,在使用者叫用的系統提供按鈕、 手勢或語音命令向後巡覽時引發。這表示您可以處理這個單一事件來跨所有裝置系列一致的方式執行應用程式中的向後巡覽。

連續體的優點

最後,也很重要,我們想要提到我們個人最愛的其中一個: 在 Windows 10 的後續發展。與後續發展的 Windows 10 調整您的經驗您想要和您想要的方式。如果您的應用程式在 1 2 上執行 Windows PC 上,例如在您的應用程式中實作連續體可讓使用者使用觸控或滑鼠和鍵盤最佳化產能。UIViewSettings 類別的 UserInteractionMode 屬性,與您的應用程式可以判斷使用者是否互動只要一行程式碼使用觸控或滑鼠和鍵盤的檢視:

UIViewSettings.GetForCurrentView().UserInteractionMode;
// Returns UserInteractionMode.Mouse or UserInteractionMode.Touch

在偵測的互動模式,您可以最佳化事後想增加或減少邊界、 顯示或隱藏複雜的功能及其他應用程式的 UI。請參閱 TechNet 文章中,"Windows 10 應用程式: 藉此運用持續性功能來變更 UI 的滑鼠/鍵盤使用者使用自訂 StateTrigger,"Lee McPherson (wndw.ms/y3gB0J) 顯示如何結合新 StateTriggers 和 UserInteractionMode 建置您自己自訂的連續體 StateTrigger。

自動調整應用程式

螢幕大小和方向的變更可以回應的應用程式很有用,但 UWP 來達成吸引人、 跨平台功能,提供開發人員提供兩種自動調整行為的其他類型:

  • 版本的自動調整應用程式回應至不同版本的 UWP 就會偵測可用的應用程式開發介面和資源。例如,您可以使用只會在同時支援您尚未尚未升級的客戶繼續執行 UWP 的最新版本的裝置上出現一些較新 Api 的應用程式。
  • 平台自動調整應用程式回應不同的裝置系列上可用的獨特功能。如此可能會在所有的裝置系列上執行建置的應用程式但要 smartphone 等行動裝置上執行時使用某些行動裝置特定 Api。

如先前所述,與 Windows 10 絕大多數的 UWP Api 是完全可存取任何應用程式,不論它執行所在的裝置。然後每個裝置系列與相關聯的特定的 Api 可讓開發人員進一步量身訂做他們的應用程式。

自動調整應用程式背後的基本構想是您的應用程式會檢查功能 (或功能) 它需要,並可用時才使用。在過去,應用程式會檢查作業系統版本與然後呼叫該版本與相關聯的應用程式開發介面。Windows 10 與您的應用程式可以在執行階段檢查是否支援類別、 方法、 屬性、 事件或 API 合約的目前的作業系統。若是如此,應用程式接著會呼叫適當的 API。Windows.Foundation.Metadata 命名空間中的 ApiInformation 類別包含數個靜態方法 (例如 IsApiContractPresent、 IsEventPresent 和 IsMethodPresent),這用來查詢的應用程式開發介面。以下為範例:

using Windows.Foundation.Metadata;
if(ApiInformation.IsTypePresent("Windows.Media.Playlists.Playlist"))
{
  await myAwesomePlaylist.SaveAsAsync( ... );
}

此程式碼會執行兩件事。這會讓執行階段檢查然後類別的執行個體上呼叫 SaveAsAsync 方法的播放清單類別的目前狀態。也請注意輕鬆檢查目前的作業系統、 使用 IsTypePresent API 上的型別存在。在過去,這類檢查可能需 LoadLibrary、 GetProcAddress、 QueryInterface、 反映、 或使用 「 動態 」 關鍵字和其他人視語言和架構而定。當進行方法呼叫也請注意強型別的參考。使用反映或 「 動態 」 時,您會遺失,比方說,告知您如果您拼錯的方法名稱的靜態編譯階段診斷。

偵測與應用程式開發介面合約

它的核心 API 合約是一組 Api。假設性的應用程式開發介面合約可能代表一組 Api 包含兩個類別、 介面五個、 一個結構、 兩個列舉等等。我們會分組在邏輯上相關的類型為 API 合約。在許多方面 API 合約表示功能 — 一組相關的 Api 可一起提供某些特定功能。從 Windows 10 每一種 Windows 執行階段 API 開始是某些應用程式開發介面合約的成員。在文件 msdn.com/dn706135 說明各種可用的應用程式開發介面合約。您會看到其中大多數都代表一組功能上相關的 Api。

使用 API 合約也提供您開發人員與一些額外的擔保。最重要的是一種平台 API 合約中實作任何應用程式開發介面時,就必須在該合約中實作每一種 API。換句話說,應用程式開發介面合約是不可部分完成的單位,而且測試該應用程式開發介面合約的支援相當於測試集中的每個應用程式開發介面支援。您的應用程式可以呼叫任何 API 中偵測到的應用程式開發介面合約而不必個別檢查每個應用程式開發介面。

最大值與最常使用的 API 合約是 Windows.Foundation.UniversalApiContract。它包含幾乎全部都在通用 Windows 平台 Api。如果您想要查看目前的作業系統是否支援 UniversalApiContract,您可以撰寫下列程式碼:

if (ApiInformation.IsApiContractPresent(
  "Windows.Foundation.UniversalApiContract"), 1, 0)
{
  // All APIs in the UniversalApiContract version 1.0 are available for use
}

現在 UniversalApiContract 只存在時版本是 1.0 版中,因此這項檢查會稍微愚蠢。但是 Windows 10 的未來更新可能會造成其他應用程式開發介面,2.0 版包含新的通用 Api UniversalApiContract 產生這種方式。在未來的應用程式想要在所有裝置上執行但也想要使用新版本 2.0 Api,可以使用下列程式碼:

if (ApiInformation.IsApiContractPresent(
  "Windows.Foundation.UniversalApiContract"), 2, 0)
{
  // This device supports all APIs in UniversalApiContract version 2.0
}

如果您的應用程式只需要一個單一方法呼叫從 2.0 版,它無法檢查使用 IsMethodPresent 直接的方法。在這種情況下,您可以使用您覺得最簡單方法。

有 UniversalApiContract 除了其他應用程式開發介面合約。大部分代表功能或一組 Api 普遍存在所有 Windows 10 平台上並改為上有一或多個特定裝置系列。如先前所述,您不再需要檢查特定類型的裝置並再推斷支援的應用程式開發介面。只需要檢查您的應用程式想要使用的應用程式開發介面的集合。

我現在可以重寫我檢查 Windows.Media.Playlists.PlaylistsContract,而不是只檢查播放清單類別的存在與否的原始範例:

if(ApiInformation.IsApiContractPresent(
  "Windows.Media.Playlists.PlaylistsContract"), 1, 0)
{
  // Now I can use all Playlist APIs
}

每當您的應用程式需要呼叫跨所有裝置系列,並不存在的 API 必須加入適當的擴充功能 SDK 可定義應用程式開發介面的參考。在 Visual Studio 2015 移至 [加入參考] 對話方塊並開啟 [延伸] 索引標籤。那里您可以找到三個最重要的延伸模組: 行動裝置的延伸模組、 桌面的延伸模組和 IoT 延伸模組。

您的應用程式要進行的動作、 但是是檢查有任何所需的應用程式開發介面合約和有條件地呼叫適當的 Api。就不需要擔心裝置的類型。現在的問題是: 我必須呼叫播放清單應用程式開發介面但不是通用的應用程式開發介面。文件 (bit.ly/1QkYqky) 告訴我在哪一個應用程式開發介面是合約的類別。但是它的擴充功能 Sdk 定義?

(其實,播放清單類別目前) 僅提供的桌上型裝置上,而不會在行動、 Xbox 和其他裝置系列。因此您必須新增任何先前的程式碼編譯之前桌面擴充功能 SDK 的參考。

Visual Studio 小組成員和偶爾 MSDN Magazine 撰寫 Lucian Wischik 建立一項工具可幫助。它會分析您的應用程式程式碼時它會呼叫特定平台 API、 確認 adaptivity 核取了其周圍。如果沒有核取了,分析器會報告一則警告,並提供方便"快速修復 「 若要在程式碼插入正確的核取只要按下 Ctrl + 點或按一下燈泡。(請參閱 bit.ly/1JdXTeV 如需詳細資訊。) 也可以透過 NuGet 安裝 「 分析 」 (bit.ly/1KU9ozj)。

讓我們來查看更完整的 Windows 10 的自動調整程式碼範例將總結。首先,這裡的一些程式碼不正確地自動調整:

// This code will crash if called from IoT or Mobile
async private Task CreatePlaylist()
{
  StorageFolder storageFolder = KnownFolders.MusicLibrary;
  StorageFile pureRockFile = await storageFolder.CreateFileAsync("myJam.mp3");
  Windows.Media.Playlists.Playlist myAwesomePlaylist =
    new Windows.Media.Playlists.Playlist();
  myAwesomePlaylist.Files.Add(pureRockFile);
  // Code will crash here as this is a Desktop-only call
  await myAwesomePlaylist.SaveAsAsync(KnownFolders.MusicLibrary,
    "My Awesome Playlist", NameCollisionOption.ReplaceExisting);
}

現在讓我們來新增一條線會確認選擇性 API 的相同程式碼,請參閱目標裝置上支援之前呼叫的方法。這樣可避免執行階段損毀。請注意您可能會想要進一步採取此範例中並不會顯示呼叫 CreatePlaylist 方法如果您的應用程式偵測到的播放清單功能的 UI 不是裝置上的可用:

async private Task CreatePlaylist()
{
  StorageFolder storageFolder = KnownFolders.MusicLibrary;
  StorageFile pureRockFile = await storageFolder.CreateFileAsync("myJam.mp3");
  Windows.Media.Playlists.Playlist myAwesomePlaylist =
    new Windows.Media.Playlists.Playlist();
  myAwesomePlaylist.Files.Add(pureRockFile);
  // Now I'm a safe call! Cache this value if this will be queried a lot
  if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent(
    "Windows.Media.Playlists.Playlist"))
  {
      await myAwesomePlaylist.SaveAsAsync(
        KnownFolders.MusicLibrary, "My Awesome Playlist",
        NameCollisionOption.ReplaceExisting);
  }
}

最後,以下是存取許多行動裝置上找到的專用的相機按鈕看起來的程式碼範例:

// Note: Cache the value instead of querying it more than once
bool isHardwareButtonsAPIPresent =
  Windows.Foundation.Metadata.ApiInformation.IsTypePresent(
  "Windows.Phone.UI.Input.HardwareButtons");
if (isHardwareButtonsAPIPresent)
{
  Windows.Phone.UI.Input.HardwareButtons.CameraPressed +=
    HardwareButtons_CameraPressed;
}

請注意偵測步驟。如果我要直接參考 CameraPressed 事件在桌上型電腦上的 HardwareButtons 物件而不檢查 HardwareButtons 存在,我的應用程式會當機。

有很多快速回應的 UI 和 Windows 10 中的自動調整應用程式如何運作。您要進一步了嗎? 簽出應用程式開發介面合約 Brent Rector 組建 2015年研討會提供絕佳談論 (wndw.ms/IgNy0I),而且一定要在自動調整的程式碼上檢視參考 Microsoft Virtual Academy 影片 (bit.ly/1OhZWGs) 來涵蓋更多詳細資料中的這個主題。


Clint Rutkas是適用於 Windows 著重於開發人員平台的資深產品經理。他曾在 343 產業 Halo 和 microsoft Channel 9 上並且已建立使用 Windows 技術,像是電腦控制的迪斯可舞廳、 自訂的 Ford Mustang、 t shirt 豬機器人及其他一些瘋狂專案。

Rajen Kishna目前擔任資深產品行銷經理 Windows 平台開發人員行銷小組 microsoft 在里德蒙現他之前曾擔任過顧問和荷蘭的 Microsoft 技術推廣者。

感謝以下的微軟技術專家對本文的審閱: Sam Jarawan、 Harini kannan Sundararajan 和 Brent Rector