Apple TVでUICollectionViewCellをハイライトする


昨日の記事では、Apple TVからKii Cloudにアクセスする方法をご紹介しましたが、UIに関する内容が一切なかったので、今回はUIに関する情報をご紹介します。
とはいえ、Traditional AppであればiOSとほぼ同様に実装することができるのでtvOSならではの情報についてまとめています。

 

Apple TVのUIコンポーネント

基本的にはiOSのものと共通した名称のものが提供されていますが、一部のコンポーネント(UISwitchなど)はtvOSには提供されていません。
また、デバイスが全く異なるので当然ではありますが、iOSと同じ名称のコンポーネントでも表示のされ方が全く異なります。
中でも、ブラーエフェクトはiOS以上に多用されており、アラートやアクションシートを表示した際は背景のビューすべてにブラーがかかり、何も見えなくなります。

Apple TV Human Interface Guidelinesより

また、Siri Remoteでの操作になるので、Apple TVでは基本的にスワイプでUIコンポーネントを選択(フォーカス)し、タップ/クリックを行うというインタラクションが基本となります。
詳しくはApple TV Human Interface Guidelinesを参照ください。

 

ビューへのフォーカス

Apple TVのUIコンポーネントをフォーカスしたとき、基本的にはそのコンポーネントがハイライト表示されます。
例えばUITableViewCellはセルのサイズや色が変わります。

Apple TV Human Interface Guidelinesより

 

UICollectionViewCellへのフォーカス時の表示を実装する

さてようやく本題です。

前述の通り、Apple TVのUIコンポーネントはフォーカスしたときにそのことがわかるようになっているのですが、UICollectionViewCellはデフォルトだとハイライト表示がされず、フォーカスしていることがわかりません。

なので、別途フォーカス時にハイライトされるようコーディングする必要があります。

以下のサンプルはXcode 7.1.1で実行しています。

 

●フォーカス時の見た目を直接指定する方法

UICollectionViewCellのカスタムクラスに以下のように実装します。

override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
    coordinator.addCoordinatedAnimations({
        if self.focused {
            self.backgroundColorUIColor.redColor()
        }
        else {
            self.backgroundColorUIColor.clearColor()
        }
    }, completion: nil)
}

didUpdateFocusInContext:withAnimationCoordinator:メソッドでフォーカスが変化した際のイベントが取得できるので、その際のフォーカス状態(focused)の値に応じてビューの見た目を定義します。

上の例では、セルが選択されたときのみ背景を赤色に変更するようにしています。

●UIImageViewを利用する方法

UIImageViewのadjustsImageWhenAncestorFocusedプロパティにtrueを指定すると、そのUIImageViewの親Viewがフォーカスされた際に、自動で拡大・ドロップシャドウが適用されます。

なので、UICollectionViewCellにUIImageViewを配置し、以下のように設定を行えばOKです。

override func awakeFromNib() {
        myImageView.adjustsImageWhenAncestorFocused = true
        ・・・
}

 

2つの方法を併用する

上記の2つを合わせて使用すれば、tvOSのホーム画面のアプリアイコンのように、フォーカス時にアイコンが拡大され、ラベルを表示するといったことも実現できます。

まず、以下のようなUIImageViewとUILabelを含んだUICollectionViewCellを定義します。
セルの定義

続いて、そのUICollectionViewCellのカスタムクラスを以下のように実装します。

class MyCollectionViewCell: UICollectionViewCell {
 
   @IBOutlet weak var myImageView: UIImageView!
   @IBOutlet weak var myLabel: UILabel!
 
   override func awakeFromNib() {
       myImageView.adjustsImageWhenAncestorFocused = true
       myLabel.hidden = true
   }
 
   override func didUpdateFocusInContext(context: UIFocusUpdateContext, withAnimationCoordinator coordinator: UIFocusAnimationCoordinator) {
       coordinator.addCoordinatedAnimations({
           if self.focused {
               self.myLabel.hidden = false
           }
           else {
               self.myLabel.hidden = true
           }
       }, completion: nil)
   }
}

すると、以下のように表示されます。
実行結果
なお、この例ではあらかじめUIImageViewに無地の画像を表示するように設定しています。
あまりないとは思いますが、UIImageViewのimageがnilの場合、その親であるUICollectionViewCellをフォーカスしても拡大・ドロップシャドウの効果は得られないのでご注意ください。

 

まとめ

tvOSのUICollectionViewCellについて、フォーカス時のハイライト表示を設定する方法をご紹介しました。

前回の記事でも書いた通り、Traditional Appとして実装する場合はiOSと共通している点もありますが、フォーカスというtvOS独自の概念やそれに対するビューの定義など異なる点も多数あります。

また、tvOS独自のTVMLを使用した実装方法もあるので、それについてはまた別の記事でご紹介したいと思います。