你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> Apple TV編程指南:使用Apple TV遙控器控制屏幕上的用戶界面

Apple TV編程指南:使用Apple TV遙控器控制屏幕上的用戶界面

編輯:IOS開發基礎

2015103102320433b224fc1c01d5d89021a1a9fffb502c.jpg

本文由CocoaChina譯者呆萌院長(博客)翻譯自蘋果開發者中心

校對:hyhSuper(GitHub)

原文:App Programming Guide for tvOS:Building Apple TV Apps--Controlling the User Interface with the Apple TV Remote

本文檔文章包括

  • Apple TV 編程指南:介紹

  • Apple TV 編程指南:創建Client-Server App

  • Apple TV 編程指南:使用Apple TV遙控器控制屏幕上的用戶界面

  • Apple TV 編程指南:檢測手勢和按鈕按壓

  • Apple TV 編程指南:設計鍵盤輸入體驗

  • Apple TV 編程指南:使用游戲控制器

  • Apple TV 編程指南:創造視差美術資源

  • Apple TV 編程指南:資源管理


使用Apple TV遙控器控制屏幕上的用戶界面

在iOS設備上,用戶通過觸屏直接進行交互。在蘋果電視上,用戶使用遙控器進行間接交互。用戶浏覽到一個特定的選項上,然後按下遙控器上一個按鈕來選擇這個選項。當用戶選中屏幕上的選項時,該選項就會變成焦點。焦點是指用戶間接地通過遠程的或者其他的輸入設備進行的輸入行為引起的屏幕的外部效果。在一個以焦點為基礎的交互模型中,在屏幕上的單一視圖可以得到焦點,並且用戶可以通過浏覽屏幕上不同的UI選項將焦點移動到其他視圖,從而引起焦點更新。得到焦點的視圖被用作任何用戶操作的目標事件。例如,如果一個屏幕上的按鈕被選中,當由遙控器發送按鈕選擇事件時,目標事件將被觸發。

UIKit框架只支持以焦點為基礎的交互,在大多數情況下,這種行為只在有意義的地方自動提供。你可以要求以編程形式焦點更新,但不能將焦點往某個方向設置或者移動。例如,UIButton對象有焦點,但UILabel對象都沒有。對於自定義用戶界面組件的應用程序,你需要實現自定義的焦點目標事件,正如Supporting Focus Within Your App中解釋一樣。UIKit庫中,如UIButton,UITextField,UITableView,UICollectionView,UITextView,UIsearchbar 以及UISegmentedControl有默認焦點。

焦點引擎控制焦點

包含可控制焦點的UIKit的系統和焦點移動稱為焦點引擎。有許多用戶可以控制焦點的輸入設備,例如(不同類型)遙控器,游戲控制器,模擬器等等。在你的應用程序中,焦點引擎監聽來自這些不同輸入設備的焦點移動事件。當一個事件發生時,焦點引擎會自動判斷更新焦點並通知你的應用程序。該系統有助於創造一個持續性的用戶體驗,即提供了每一個應用程序中所有當前和未來的輸入方法的自動支持,並幫助開發人員專注於實現他們的應用程序的獨特行為而不是定義或重塑基本的導航。

只有焦點引擎才能顯式更新焦點,這意味著沒有一個可直接設置焦點的視圖或移動焦點往一個特定方向的接口。如果用戶發送一個移動事件,如果焦點引擎系統要求更新,或者如果應用程序請求更新,該焦點引擎只更新焦點。要了解更多關於如何手動更新的焦點,請參看 Updating Focus Programmatically 一節。

焦點引擎控制主要是確保焦點不在屏幕上意外地移動,並且它的行為在不同的應用程序中是相似的。這有助於防止用戶對不同的行為感到困惑,同時意味著開發人員不必自己定制適當的焦點管理解決方案。

UIFocusEnvironment協議

焦點引擎通過UIFocusEnvironment協議,與你的應用程序進行通信。 UIFocusEnvironment 協議定義了視圖層次結構的一個分支的焦點行為。UIKit庫中遵循這個協議的類有UIView、UIViewController、UIWindow 和 UIPresentationController,換句話說,這些類都直接或間接地控制在屏幕上的視圖。在視圖和視圖控制器中重寫UIFocusEnvironment協議方法,你可以在應用程序中控制焦點行為。

用戶生成的焦點移動

焦點引擎可以根據遙控器或者其他輸入設備的響應事件自動決定焦點應該移動到哪裡。用戶可以將焦點轉移到任何二維方向:上下左右或對角線(如果硬件支持的話)。例如,如果用戶左滑,焦點引擎試圖直接找到在當前獲得焦點的視圖左邊的一個視圖,這個視圖必須具有可以獲得焦點的特性。如果一個新的視圖被發現,則焦點移動到該視圖;否則,焦點停留在當前激活的視圖。

如果輸入設備支持,焦點引擎也自動處理復雜的行為。例如,基於運動的遠程滑動,根據焦點速度調節焦點相關的動畫速度,播放導航的聲音,和當焦點移出屏幕,時更新滾動視圖偏移。要了解更多關於焦點相關的動畫,請參看 UIFocusAnimationCoordinator類參考。

決定在哪裡移動焦點

當決定如何按照用戶動作移動焦點時,焦點引擎需要應用程序內部的用戶界面和所有的具有可獲得焦點特性的所有視圖的可視區域。這意味著,如果一個可獲得焦點的視圖在完全在另一個可獲得焦點視圖的下面,那麼它將會被忽略,不能得到焦點。也就是說部分區域隱藏的視圖,只有可見部分才能獲得焦點。利用這一技術,焦點引擎從當前獲得焦點的視圖開始,在運動路徑上直接找到可以獲得焦點的區域。搜索區域的大小與當前焦點視圖的大小直接相關。

圖 3-1焦點移動

QQ截圖20151123164723.png

如果焦點引擎找到一個新的視圖去移動焦點,那麼它會在移動焦點發生之前給你的應用程序一個驗證移動的機會。操作系統在每個包含上一個和下一個焦點視圖的焦點環境上都會調用 shouldUpdateFocusInContext:方法。先通知先前的焦點視圖,然後是焦點視圖,最後通知父視圖。如果所有焦點環境 shouldupdatefocusincontext:的返回值為NO,那麼這個焦點移動將會被取消。要了解更多關於焦點環境的知識,參見 UIFocusEnvironment Protocol Reference.

初始焦點和首選焦點鏈

當一個應用程序啟動時,焦點引擎決定一個默認的焦點視圖獲得焦點。這個視圖通常是距屏幕左上角最近的一個可獲得焦點的視圖。

圖 3-2分層搜索的初始視圖,以獲得焦點。

QQ截圖20151123164847.png

但是,使用 UIFocusEnvironment 協議的首選焦點視圖,可以為你的應用程序提供默認情況下焦點該去哪的線索。當設置初始化焦點時,焦點引擎首先詢問 window 的首選的焦點視圖,這個視圖就是根視圖控制器的 preferredFocusedView 對象。因為返回值是一個符合 UIFocusEnvironment 協議的 UIView 對象,所以焦點引擎詢問其首選的焦點視圖,以次類推。這個由一系列作為返回值的首選焦點視圖組成的鏈表是首選焦點鏈。焦點引擎遵循這個首選焦點鏈,直到得到的焦點視圖是它本身或者是nil。從首選焦點鏈中的最後一個列表中選擇位置最深處的視圖作為下一個可獲得焦點的視圖。

下面這個例子展示什麼是首選焦點鏈:

  1. 焦點引擎向根窗口查詢 preferredFocusedView,並返回它的根視圖控制器下的 preferredFocusedView。

  2. 根視圖控制器是選項卡視圖器的時候,返回值是它的被選者的視圖控制器的 preferredFocusedView 對象。

  3. 被選擇視圖控制器重寫其 preferredFocusedView 方法,返回一個特定的 UIButton 實例對象。

  4. 這個 UIButton 實例對象返回 self(默認值),並可獲得焦點,所以它被焦點引擎選擇作為下一個焦點視圖。

正如首選焦點鏈所定義的那樣,每當焦點在一個指定的視圖更新時,新的焦點視圖都會被設定為首選焦點視圖。焦點鏈的另一個例子,當有一個視圖控制器呈現在當前焦點視圖的上面時,焦點引擎會使用它的首選焦點鏈更新焦點到新的視圖控制器上。
焦點更新

當用戶行為引起了焦點運動時就會引起焦點更新(例如,在遙控器上滑動),這時應用將會請求更新焦點或者系統自定觸發更新焦點。

焦點更新的解析

當焦點更新或者焦點移動到一個新的視圖的時候,無論焦點視圖是子視圖或者不同於這個視圖層級的部分,都將會有下列事情發生:

  • focusedView 屬性被更新,並且更新的效果會反應到最新的到焦點的視圖或者首選焦點視圖上。

  • 焦點引擎使用didUpdateFocusInContext:withAnimationCoordinator:方法通知每一個焦點環境,包含先前焦點視圖或下一個焦點視圖(焦點更新後的視圖)的焦點環境。焦點更新時,系統會使用動畫協調員安排焦點更新相關的動畫。詳見 UIFocusAnimationCoordinator。

  • 在所有相關的焦點環境得到通知後,所有的協調動畫都在同一時間運行。

  • 如果下一個焦點視圖是在一個滾動視圖上,並且在屏幕以外,那麼滾動視圖將會滾動到該視圖所在的位置,使它移進屏幕內。

系統生成的焦點更新

在許多常見的情況下,必要的時候UIKit會自動更新焦點。下面的幾個例子展示了什麼情況下系統會自動的更新焦點:

  • 從視圖層次結構中移除一個焦點視圖。

  • UITableView 或 UICollectionView 重新加載數據。

  • 在當前獲得焦點的視圖上展示一個新的視圖控制器。

  • 用戶按下遙控器上的菜單回退。

以編程方式更新焦點

通常情況下,焦點會在必要的時候自動更新,但是有時候,你需要在應用程序內部,用代碼主動引起焦點更新。任何焦點環境通過調用 setNeedsFocusUpdate 方法請求焦點更新,這個方法重置了焦點環境的 preferredFocusedView。下面是一些何時可以在你的應用內部主動的更新焦點的例子:

  • 如果應用程序的內容發生變化,那麼為了留在用戶所期望的地方,則需要改變焦點。例如:音樂類應用程序總是希望專注當前播放的歌曲。當一首歌曲結束時,應用程序應該請求更新的焦點,並移動到播放列表中得下一首歌曲。

  • 用戶期望焦點轉移到某個新的地方的操作行為。例如:一個應用程序的界面由兩個部分組成,左邊是一個菜單,右邊是對應菜單項的內容集合。當用戶在菜單項之間移動時,右邊的內容更改。當用戶選中一個菜單項時,他們可能會期待焦點自動移動到選定的菜單項集合中的第一項。

  • 得到焦點的自定義的焦點控件,更新它的內部狀態時需要以某種方式改變焦點。例如: 當用戶在遙控器上選定選取器件時,焦點會移動到這個控件上,讓用戶選取選取器上的一系列選項。按下遙控器上的菜單又會導致改控件獲得焦點。在這種場景下,通過 preferredFocusedView,選擇控件會發出請求更新焦點移動到它的一個子視圖上。

讓你的APP支持焦點

如果你的應用程序使用內置 UIKit 控件,你的應用程序什麼都不用做就可以支持焦點:在應用程序啟動時,屏幕上的一個可獲得焦點的視圖會被選擇作為最初的焦點視圖,在應用程序的運行周期中,焦點引擎負責管理焦點。

然而,對於大多數應用程序來說,都希望實現某些自定義的焦點行為,例如,當焦點改變時,更新應用程序狀態,創建新的用戶交互界面元素類型,並實現自定義的焦點動畫。下面的章節概述了在你的應用程序中實現支持自定義焦點行為需要做什麼。

對一個視圖層級結構的分支來說 UIFocusEnvironment 類控制焦點相關行為。這意味著控制器控制著它的根視圖和子節點視圖的焦點相關行為,並且 UIView 類型對象控制它自己和它子節點的焦點行為。因此,多個焦點環境,可以控制同一個視圖層級結構的分支的焦點相關行為。視圖層級結構分支是指視圖不但包含其他視圖,而且還在視圖控制器中。控制焦點相關行為並不是意味著某個視圖獲得焦點,而是意味著焦點環境可以控制焦點在它的視圖層級上如何移動,在焦點環境下的視圖層級上焦點改變後,UI如何應對。

在視圖控制器中支持焦點

因為 UIViewController 遵循 UIFocusEnvironment 協議,所以在你的應用程序中,自定義視圖控制器可以重寫 UIFocusEnvironment 委托方法來實現自定義的焦點行為。自定義視圖控制器可以實現如下功能:

  • 重寫 preferredFocusedView 方法指明焦點默認開始的視圖。

  • 重寫 shouldUpdateFocusInContext: 方法來定義焦點允許移動的位置。

  • 在更新你的應用程序的內部狀態或者焦點更新發生時,重寫 didUpdateFocusInContext:withAnimationCoordinator: 方法來對焦點更新。

通過調用 setNeedsFocusUpdate 方法,你的視圖控制器可以請求焦點引擎為當前的 preferredFocusedView 重置焦點。注意,只有視圖控制器包含當前焦點視圖,調用setneedsfocusupdate 才有效果。

在Collection視圖和Table視圖中支持焦點

當使用 collection 視圖和 table 視圖工作時,你可以使用委托對象來定義任何自定義行為。這種模式也可以基於焦點交互界面實現時使用。UITableViewDelegate 和UICollectionViewDelegate 協議聲明的方法和屬性和 UIFocusEnvironment 協議提供的屬性和方法相似,但是 tableView 和 collectionView 的協議是規范他們自己的行為的。

在collection視圖和table視圖中支持焦點的提示:

  • 使用 UICollectionViewDelegate 的 collectionView:canFocusItemAtIndexPath: 方法或者 UITableViewDelegate 的 tableView:canFocusRowAtIndexPath: 方法去檢查某個特殊的 cell 是否需要焦點。這一行動的工作類似於在一個自定義視圖中重寫 UIView 的 canBecomeFocused 方法。

  • 當焦點離開當前視圖時,使用在 UICollectionView 和 UITableView 中都有定義的 remembersLastFocusedIndexPath 屬性,檢查焦點是否應該返回上一個焦點索引, 指定焦點是否應返回焦點離開時的最後一個焦點索引路徑,然後焦點重新進入 collectionView 或者 tableView 視圖。

在自定義視圖中支持焦點

像 UIViewController 和 UIView 類也遵循 UIFocusEnvironment 協議,這意味著 Supporting Focus in View Controllers 文檔中概述的所有的功能都可以應用到自定義的視圖中。但是,因為視圖可以獲得焦點,所以在你實現自定義的焦點行為的時候,需要考慮下面的幾個因素:

  • 如果你的自定義視圖需要焦點,重寫 canBecomeFocused 方法並設置返回值為 YES(默認情況下,它的返回值為NO)。你的視圖可能經常得到焦點或在某種情況下才能得到焦點。例如,UIButton 對象的 enable 屬性為 NO 的時候,它不能得到焦點。

  • 如果聚焦這一觀點必須重新聚焦到另一個視圖(例如,一個子視圖),選擇重寫 preferredFocusedView。

  • 更新你的應用程序的內部狀態或者焦點更新發生時,重寫 didUpdateFocusInContext:withAnimationCoordinator: 方法作為焦點更新後的反應行為。

協調焦點相關動畫

當焦點發生更新時,當前視圖以某種動畫的形式過度到焦點狀態,之前的焦點視圖以某種動畫形式過度到非焦點狀態,焦點更新後獲得焦點的視圖將以某種動畫形式過度到焦點狀態。然而,這些動畫和你應用程序中定義的常見的動畫不同,為了實現某種系統級別的行為,UIKit 使與焦點相關的動畫的曲線軌跡和運動時間相適應。例如,當焦點正在快速移動時,動畫的時間會縮短,以跟上用戶的移動。

UIKit提供系統定義的有關可以獲得焦點的視圖類的焦點動畫。使用 UIKit 的內置 UIFocusAnimationCoordinator 類和 addCoordinatedAnimations:completion: 方法,可以創建帶有系統級行為的自定義動畫。

根據協調器提供了的焦點環境,被添加到協調器中的動畫可以作為正在獲取焦點的動畫中的邊緣動畫,或者失去焦點中得動畫,或者兩者都不是。一般情況下,獲得焦點和失去焦點的父視圖,和特殊的焦點視圖的父視圖一樣,將會沿著獲得焦點的方向做動畫。非焦點視圖獨有的父視圖將會做失去焦點的動畫。

圖 3-3自定義焦點動畫

QQ截圖20151123170743.png

通常,視圖擁有不同的動畫,取決於他們正在得到焦點或失去焦點。通過重寫視圖的 didUpdateFocusInContext:withAnimationCoordinator: 方法和檢查視圖的當前焦點的狀態的上下文,你可以指定視圖需要哪種動畫。下面是重寫 didUpdateFocusInContext:withAnimationCoordinator: 方法的例子。

- (void)didUpdateFocusInContext:(UIFocusUpdateContext *)context withAnimationCoordinator:(UIFocusAnimationCoordinator *)coordinator
{
    [super didUpdateFocusInContext:context withAnimationCoordinator:coordinator];
 
    if (self == context.nextFocusedView) {
        [coordinator addCoordinatedAnimations:^{
            // focusing animations
        } completion:^{
            // completion
        }];
    } else if (self == context.previouslyFocusedView) {
        [coordinator addCoordinatedAnimations:^{
            // unfocusing animations
        } completion:^{
            // completion
        }];
    }
}

非焦點和焦點視圖共同的父視圖,可以為焦點視圖和非焦點視圖一起關聯相關動畫。例如,一個 UICollectionView 對象可以將之前獲得焦點的cell以及將要獲得焦點的 cell 一起做動畫。在對 UICollectionViewCell 的子類情況下,推薦使用上面代碼片段的相似邏輯,並在子類中實現動畫代碼。

調試焦點問題

當應用程序運行時,UIKit幫助你調試的焦點問題。

為什麼這個視圖不能獲得焦點?

一個被期望獲得焦點的視圖卻不能獲得焦點的原因有很多種,下面列舉了幾種可能的原因但並不是全部原因:

  • 視圖的 canBecomeFocused 方法返會值為 NO 。

  • 視圖的 hidden 屬性值設置為 YES 。

  • 視圖的透明度屬性值為 0 。

  • 視圖的用戶交互被禁用。

  • 這個視圖被它上面的視圖完全遮蓋。

UIKit 提供的 UIView 類的隱藏方法——_whyIsThisViewNotFocusable,目的是為了幫助測試所有前面提到的常見情況。此方法僅是在調試一個特別的視圖引用時調用,並打印出一個具有可讀性並且可能引起問題的如下所示的列表:

32.png

為什麼焦點移動到你沒有想到的某個地方?

有時候,焦點並沒有移動到你所期待的地方,或者它根本就沒有移動。焦點引擎提供了很多便利,有時候你最好了解關於它是如何移動焦點的更多信息。  

UIKit發送了一個可視化的關於焦點引擎在 Quick Look 中如何搜尋下一個焦點視圖的 UIFocusUpdateContext 實例對象。為了看到這個場景,可以在shouldUpdateFocusInContext: 或者 didUpdateFocusInContext:withAnimationCoordinator: 方法中設置斷點,當程序運行到這個斷點時,在調試台中選中 context 參數並代開 Quick Look 菜單選項。

圖 3-4在調試器中選擇上下文參數

ContextParameter_2x.png

如果斷點在焦點運動的過程中被執行(不是焦點更新時), Quick Look會展示一張圖片來表達搜索引擎找到下一個焦點視圖的搜索路徑。例子如下3-5圖。

圖 3-5快速尋找一個圖像顯示

QuickLookPresentationOfImage_2x.png

下面是 Quick Look 中圖片可能展示的幾種信息

  • 以前的焦點視圖(搜索的開始視圖),顯示在紅色區域。

  • 搜索路徑輪廓,用虛線標注。

  • 任何在搜索路徑中可獲得焦點的 UIView 對象區域,顯示紫色。

  • 任何在搜索路徑中可獲得焦點的 UIFocusGuide 類區域,顯示藍色。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved