現在JavaScriptの設定が無効になっています。このページを利用するにはJavaScriptの設定を有効にしてください。2016の16日目の記事です。一覧はこちらみなさんこんにちは。2016の最終日を担当させていただきます林(@kazuhiro4949)です。ヤフーでは普段iOSアプリの開発に携わっているのですが、今年の9月にYahoo!ショッピングのtvOSアプリも開発させていただきました。TV(第4世代)をお持ちの方もしよければ触ってみてください。今回はそのtvOSアプリについて書きます。tvOSアプリを開発する場合、そのやり方には大きく分けて2種類あります。Apps”と呼ばれています。App”はウェブアプリとして開発するタイプで、TVML・TVJSというApple独自の技術を使います。Apps”として実装すると、「ほぼ」iOSアプリと同じように実装できます。FoundationやUIKitといったフレームワークは一部を除いてそのまま使うことができ、アプリの基本構造はiOSと変わりません。Apps”を選びました。いざ実装してみると「こんな感じのUIってどう作ればいいんだろう...」と思うところがいくつか出てきました。そこで、UIの実装でちょっと一手間必要なポイントを書き残しておこうと思います。今後開発を検討されている方たちへのノウハウとしてお役に立てれば幸いです。文中のコードはSwift2.3で実装しています。検索のUIを作る作りはじめていきなりつまずいたのが、よくある検索窓を持つUIでした。iOSアプリの場合、iOS8以降ではUISearchControllerを使って作ると思います。tvOSにもそのクラスは存在しているため、tvOSアプリで見慣れた検索画面は同じようにすぐ作れるものだと思っていました。いざ実装し始めてみると、「検索窓を置く場所」に迷うことがわかりました。典型的なものとしては、検索窓を埋め込んだViewをUITabBarControllerのいち要素として表示させます。https://developer.apple.com/tvos/human-interface-guidelines/interface-elements/#text-and-search)そんな時に使えるのがUISearchContainerViewControllerです。こいつはtvOS用に使うことができます。UINavigationControllerやUITabBarControllerの子として検索窓を配置するために使用します。searchContainerController)こうすると、標準アプリのような検索結果画面を表示させることができました。Developerのフォーラムを参考にしました。Storeアプリをはじめ、大半のtvOSアプリはシンプルなUIが採用されています。多くのものがUICollectionViewの上へ、画像+ラベルのセルを表示させるだけという構成になっています。https://developer.apple.com/tvos/human-interface-guidelines/visual-design/)単純なUIに見えて意外と一手間必要だったのが、UILabelのフォーカス時アニメーションです。UIImageViewの場合、adjustsImageWhenAncestorFocusedというプロパティー値を変更するだけでアニメーションがつけられます。一方でUILabelはそのような設定がなく、そのままではフォーカスされた画像に重なってしまいます。そこで、これらに対しては自分でフォーカスアニメーションを作る必要があります。coordinator:)というメソッドです。その中でUILabelの位置や色を調整していきます。tvOS用のメソッド。リモコンをスワイプして、このセルにフォーカスが当たる・フォーカスが外れるタイミングで呼ばれる。そのときに自分自身のフォーカス状態に応じたアニメーションをUIFocusAnimationCoordinatorの中で記述する。Shelfように各セクションへタイトルを付けている場合、それはそれでフォーカスされた画像と重ならないようにする必要があります。セクションのタイトルの場合厄介なのは、タイトルの位置を固定しながら横にCollectionViewをスクロールさせ、フォーカスされているCellと重なっているか判定する必要があります。必要があればそれも同様に対応しましょう。することで、「らしい」UIを実現できました。任意のViewへフォーカス時のアニメーションをつける続いて、任意のViewがフォーカスされた時のふわっと浮き出る画面の作り方です。Movieアプリの説明文のように、任意のViewに対してフォーカスがあてられるようにしたいと思ったのですが、残念ながらUIViewに対してはフォーカスアニメーションが存在していません。そのため、自前で実装しなければなりません。単純にフォーカスがあたった時にViewを浮かせたいのであれば、CGAffineTransformでViewをScaleさせつつ影を設定することでできます。tvOSアプリが持つフォーカスの概念では、それに加えてリモコンのタッチパネルをグリグリした時Viewが一緒に合わせて動くという特徴を持っています。https://developer.apple.com/tvos/human-interface-guidelines/user-interaction/)この動作はどのように実現するのか調べてみると、iOSでは7から利用可能なUIMotionEffectによる視差効果がそのままグリグリさせたときの効果として使えました。Remote上で指を動かした時にViewへ上下の視差効果を与えるコードを書きます。UIMotionEffectGroupを生成します。作成したグループはフォーカスイベントの時につけたり外したります。}()}フォーカスがあてられた時に奥行きをつけるために、layerへ影を設定します。}}Viewに対してフォーカスをあてられるようにするには、専用のメソッドをオーバーライドします。}}続いてアニメーションを実装します。フォーカスがあたったり外れたりすると、対象となるViewで以下のメソッドが呼ばれます。Remoteのタッチパネルをクリックした時にViewが奥へ押されるアニメーションを追加しましょう。Viewに対するプレス判定は専用のメソッドがあるので、それをoverrideします。}}以上の実装でフォーカスを当てると浮き上がり、指の動きに合わせた視差効果も持つViewを作成できました。ちなみに標準で上記の視差効果を持っているUIパーツはUIImageViewとUIButtonです。それ以外の場合ではUIMotionEffectを利用した視差効果をつけましょう。NavigationBarの領域にあるコンテンツを隠すtvOSではデフォルトではUINavigationBarが透明になっています。そのためtranslucentを設定している場合、スクロールするとNavigationBarの領域にも表示されてしまいます。この状態を避けるためにNavigationBarへViewを置いたり色を設定したりなどが考えられるかと思います。他のアプリを調べていると、多くのものではNavigationBar領域は背景が表示されつつコンテンツは何も表示されないという形になっていました。そのUIは、UIViewControllerへmaskViewを設定することでできます。マスクする領域に相当するViewを作ります。CAGradientLayerでグラデーションをかけて、徐々にViewが消える感じを出します。Catalogにそういった目的のクラスが作られており、これをベースに作っていくのがいいでしょう。GradientMaskView.swiftでは、UIViewControllerへCAGradientLayerを適用しましょう。この機能はUINavigationControllerに保持されているViewController共通で持っていると嬉しいでしょう。Extensionですね。Extensionで拡張します。ここではviewWillLayoutSubviewsのイベントでレイアウトを調整しています。}}これで、以下のようにNavigationBarの領域へは何も表示されないようになりました。RemoteにはMenuボタンがあります。何もしなかった場合、以下のように動作をします。Stackの一つ前に戻るiOSアプリでステータスバーを押した時と同じようにUICollectionViewの一番上へ戻したい場合は、Menuボタンが押されたときの操作をカスタマイズする必要があります。画面上の任意のセルでMenuボタンを押すと先頭のセルに戻る先頭セルでもう一度Menuボタンを押すとタブバーへフォーカスが当たるようにしましょう。Menuボタンが押されたときの処理をフックするには、UITapGestureRecognizerを使います。Remoteのタッチパネルへ触れる操作にも反応してしまうため、「Menuボタンが押された」ということのみへ反応させます。}}上記のコードの通り、リモコンを押した時の操作はiOSアプリと同じように制御できます。続いて、画面上の先頭要素へフォーカスを当てる処理を書いていきます。そのためにはフォーカスされる要素を変更するための命令を送りましょう。collectionView?.setNeedsFocusUpdate()}UICollectionViewであれば、これでindexPathForPreferredFocusedView(in:)というメソッドが呼ばれます。0)を返してやれば大丈夫です。0)}Menuボタンを押すとiOSアプリでステータスバーをタップした時のような挙動をするようになりました。最後に以上自分が気がついた範囲で書いてみました。tvOSアプリ開発はiOSアプリエンジニアであれば想像以上にすんなりと取り組めるようになっています。Engineなどの一部の独特な概念と、ここで書いたような細かいUIのTipsをおさえるだけですぐに入っていくことができます。Storeが盛り上がるのを期待しています。2016を最後まで読んでいただきありがとうございました。それではみなさん良いお年をお過ごしください。(tvOS)現状最も参考になる資料はこのサンプルコードだと思います。tvOS10にも対応されていました。tvOStvOSの技術に関する概要的な話はこちらの情報が参考になります。JAPANでは情報技術を駆使して人々や社会の課題を一緒に解決していける方を募集しています。詳しくは採用情報をご覧ください。JAPANのサービス開発を支える技術やデザイン、文化を発信しています。Reserved.このページの先頭へ。