2017/11/26

UWP - 開發 Xbox App 處理 XY navigation

只要是 Windows 10 的作業系統都可執行 Universal Windows Platform 開發的 Apps,當然包括 Xbox one。
本篇介紹移植 App 到 Xbox 時需要調整的地方。

開發 Xbox 上的 App 有幾個重點:

根據 Designing for Xbox and TV 的説明,做在沙發使用 gamepad 或 remote 去控制 TV,這個行爲被稱爲 10-foot experience,因爲通常沙發跟電視的距離約 10 feet;而 2-foot experience 説明的是 PC。
開發 Xbox 的應用要把握這個距離原則,做到幾個重點:
  • Simple
    解析度與距離的關係,用戶很難處理畫面太多的資訊,應該保持乾净的設計,減少到最簡單的畫面元件,可能畫面會接近在 Mobile 的内容而不像 Desktop 這麽多元
  • Coherent
    App 設計應該簡單容易操作,是 focus 清楚,移動的距離,階層,路徑都是一致且最少步驟就能完成想做的事情。
  • Gamepad and remote control
    重要的步驟,決定用戶如何操作 gamepad 或 remote 使用 App 的功能又不會不方便,參考 XY focus navigation and interactionMouse mode 調整操作元件的方式。開始前建議先使用 keyboard 操作 App 找到那些畫面或是元件的問題,再開始調整

    上圖是 gamepad 與 remote 按鈕的差別與介紹,按鈕的使用建議優先支援共用的會比較好,例如:X/Y/A(select)/B(back) buttons 與 menu/views button。按下 B(back) button 時,可利用 SystemNavigationManager.BackRequested 直接控制。
    gamepad 的按鈕上也額外支援一些特定的控制項,例如:ScrollViewer 的就可以用 left/right trigger 快速垂直 scroll,可參考 Gamepad and remote control
  • XY focus navigation and interaction
    gamepad 或 remote 只支援移動到擁有 IsTabStop = trueVisibility = visible 的控制項,可參考 Keyboard interactions。同理如果支援 keyboard 操作的更完整,您的 App 將會變的更方便。
    利用 FocusManager.GetFocusedElement 得知現在那個控制項被 focus,用於瞭解目前 focus 到底跑到哪裏。
    page.GotFocus += (object sender, RoutedEventArgs e) =>
    {
        FrameworkElement focus = FocusManager.GetFocusedElement() as FrameworkElement;
        if (focus != null)
        {
            Debug.WriteLine("got focus: " + focus.Name + " (" +
                focus.GetType().ToString() + ")");
        }
    };
    有些狀況可能造成 XY navigation 移動到非預期的對象:
    • IsTapStop 或是 Visibility 設定錯誤
    • 被 focus 的控制項實際上比看到的還要大,因爲 XY navigation 使用的是 ActualWidth/ActualHeight
    • 不支援重曡的控制項被 focus,一次只能 focus 一個控制項
    UWP 會預設自動計算 focus 要移動的方向與對應的控制項,但是它無法保證真的符合用戶的需求。如果 XY navigation 走向的位置不符合預期的話就要覆寫控制項的 XY navigation,强迫給定每個控制項的位置關係,可以參考 Overriding the default navigation
    如果覆寫 XY navigation 不需要重覆指定,例如: Button1.XYFocusLeft = Button2 而在 Button2.XYFocusRight = Button1
    如果覆寫 XY navigation 控制項内的子控制項一樣會承接這個設定。
    如果 XY navigation 是正常的,但是 focus visual 在 focus 時沒有顯示,可以參考下面的排除方式:
    • re-template 控制項,而且拿掉 focus virtual。搭配 UseSystemFocusVisuals="True" 或是手動加入 focus visual 來確認
    • 利用 Focus(FocusState.Pointer) 移動 focus 確定控制項有被 focus。通常會用 Focus(FocusState.Programmatic)。
    Path of least clicks:設計最短的操作距離讓用戶可以完成任務,減少畫面左右滑動的設計,讓用戶上下移動就可以完成。
    CommandBar 與 ContextFlyou:ContextFlyout 可以處理 gamepad 上的 menu 按鈕來完成;CommandBar 在 Xbox 上的操作不是這麽容易,建議改用 ContextFlyou 或是其他元件代替,可參考 Problem: UI elements located after long scrolling list/grid
  • Mouse mode
    App.xaml.cs 的建構子加入 disable mouse mode:
    public App()
    {
        this.InitializeComponent();
        this.Suspending += OnSuspending;
    
        if (IsXbox())
        {
            Application.Current.RequiresPointerMode = ApplicationRequiresPointerMode.WhenRequested;
        }
    }
    
    static string deviceFamily;
    
    public static bool IsXbox()
    {
        if (deviceFamily == null) 
        {
            deviceFamily = Windows.System.Profile.AnalyticsInfo.VersionInfo.DeviceFamily;
        }
    
        return deviceFamily  == "Windows.Xbox";
    }
    
    另外,有些 Control 則需要 Mouse mode 來操作,需要另外加入 IsEngagementRequired="true",這樣 Control 才會被進入並開啓 Mouse mode,例如: MapControl。
    <Page>
        <Grid>
            <MapControl IsEngagementRequired="true"
                        RequiresPointer="WhenEngaged"/>
        </Grid>
    </Page>
    
    另外, Page 支援設定 RequiresPointer="WhenFocused" 其他控制項目不可以設定這個屬性,如果是 full screen 的呈現時,例如看 video 時,不希望有 mouse mode 出現,可以在該 Page 設定 RequiresPointer="Never"
  • Focus visual
    focus visual 是周圍邊框表示目前控制項被關注,幫用戶簡單的知道目前位置與瀏覽的方向。
    雖然把 focus visual 的控制設定好可以跨所有裝置,但是在 10-foot experience (電視或更大的屏幕)還是有些不同。
    因爲畫面太大用戶很難一次看到全部的範圍,因此在 focus visual 需要更明顯與清楚的顯示,避免用戶做視覺的搜索。
    電視設計不像鍵盤,建議預設就幫用戶關注一個控制項目,讓用戶方便找到瀏覽方向。
    整理幾個重點:
    • Initial focus visual placement
      當 App 被啓動或是進去某個 Page,請幫用戶自動 focus 到畫面中你預期開始操作的位置。
      例如:photo app 預設選擇第一張圖片;music app 預設選擇第一首歌曲。
      也可以預設將焦點放在左上角區域,因爲大部分的 App 操作流程都是從左上角開始。
    • Making focus clearly visible
      建議屏幕是始終有一個焦點,用戶就能快速找到關注的地方。但是如果畫面是一個 full screen 的 video / photo / documents 就不一定適合。
    • Customizing the focus visual
      每個控制項目都具有一些焦點視覺相關的屬性可以調整,也可以使用 VisualState 定義不同狀態下要顯示的樣式。另外,進階一點使用 Visual layer 的效果做到一些焦點的特效。
    • Light dismiss overlay
      爲了使用戶注意當前用 gamepad 或是 remote control 操作的 UI 元素,UWP 自動添加了一個 Smoke layer 讓彈跳式 UI 在顯示時自動遮住背後的内容,讓用戶專注在彈跳出來的内容。
      這個不需要額外的處理,但要注意在使用 FlyoutBase 的控制項時可以操作 LightDismissOverlayMode 屬性設定是否要顯示 smoke layer。可參考 Modal vs light dismiss
  • Focus engagement (非常重要)
    Focus engagement 讓使用 gamepad 或 remote control 更容易操作 App。
    設定 Focus engagement 不會影響 keyboard 或是其他輸入裝置。
    設定 FrameElementIsFocusEngagementEnabled = "True" 時,代表控制項請求 focus engagement。
    用戶使用 gamepad 移動到該控制項時,需要按下 A/Select 按鈕才能與它互動。操作完成之後需要按下 B/Back 按鈕才會離開該控制項,繼續瀏覽其他控制項。
    • Focus trapping
      Focus trapping 代表的是當用戶在瀏覽控制項時突然在某個控制項直接陷入到裏面,造成用戶原本預期是到下一個控制項但是卻跑到裏面。
      利用下圖的範例來説明:

      有 3 個控制項: button1, slider, button2, 當用戶操作預期從 butotn1 到 button2 時會遇到卡在 slider 裏面,不管左右移動都是在移動 slider 的光棒。
      要解決這樣的問題有很多方式,最簡單從排版方式下手如下圖:

      或者搭配 XY focus navigation and interaction 改寫控制項的 XY focus。
      另外可以設定 Slider 的 IsFocusEngagementEnabled = "True",而操作的結果如下圖:
    • Items controls
      其他設定 engagement 的控制項有: ListView, ListBox, GridView, FlipView

      如上圖要從 top button 移動到 bottom button,用戶會預期按往下按鈕就會直接到,事實上當進去 ListView 時就會自動 focus 到第一個 item,而用戶要一路走到最後一個 item 才能離開 ListView 到 bottom button,相反的如果要回去 top button 則是要走到第一個 item 才能出去。
      這樣的操作會讓用戶抓狂,所以需要設定 IsFocusEngagementEnabled = "True",變成如下的操作流程:
      如果是 ScrollViwer 需要考慮用法:
      • 内容有其他控制項,預設進去 ScrollViewr 會自動 focus 到第一個控制項,允許用戶左右移動瀏覽不同的控制項目;
      • 内容為文字瀏覽或是圖片瀏覽時,則需要設定 IsFocusEngagementEnabled = "True",讓用戶方便進入與離開内容;更可以設定 IsTapStop = "True",讓操作不需要透過 engage 的方式,而是焦點直接放在 ScrollViewer 直接 scroll 移動。
    • Focus engagement defaults
      有一些控制項因容易操作焦點迷失(例如自動 engage 造成 focus 消失)而預設的 IsFocusEngagementEnabled 是 false,但我們還是可以打開它,下面列出幾個常使用的控制項:
      ControlFocus engagement default
      CalendarDatePickerOn
      FlipViewOff
      GridViewOff
      ListBoxOff
      ListViewOff
      ScrollViewerOff
      SemanticZoomOff
      SliderOn

還有很多開發與設計上面需要注意的地方,本篇先寫到這裏下一篇將繼續介紹: UI element sizing, TV-safe area, Color, Custom visual state trigger for Xbox, ... 等。

[補充]
  • 由於 App 在 Xbox 上可用記憶體有限,建議跟 Desktop/Mobile 的專案切開,因爲記憶體的控制會是花最多時間的地方
  • 上架到 Dev Center 時,可以搭配 TargetDeviceFamily 切開讓 Xbox 是另外一個安裝檔
  • UWP App 在封裝時, Version 只能用到前 3 碼 (例如: 1.0.0.{不可用}),最後一碼是不可以用的,因爲微軟把它用來顯示特定的設備,例如:Xbox 上安裝 App 之後會發現版本號碼變成了 1.0.0.6

更多詳細的内容,參考 What's new for developers in the latest update of UWP on Xbox One
======
開發 Xbox 的 App 最大難度在於 focus 的控制,因爲 XAML 的組合會造成 focus 的困難或是迷失,
建議 Xbox 跟 Desktop/Mobile 分開 UI 設計比較好,另外 Xbox 通常搭配電視(或是更大的屏幕)與眼睛距離較遠,内容簡單清楚是必要的。
最後因爲用戶沒有游標時,對於内容過長或是過多時都會讓用戶需要不斷地點擊方向鍵,是非常苦難的。
所以多做一些 Master Detail 的分層,讓畫面乾净與容易操作。
希望對大家有所幫助,謝謝。

References:

沒有留言:

張貼留言