おやゆびでおをApple Digital AVアダプターなどを使ってテレビに映せるようにしたいと年末年始に取り組んでました。iPad2やiPhone4Sのようにミラーリング対応機種なら一応映すことは可能でしたが、再生画面がフルスクリーンにならなかったりしましたし、それ以外の機種のことも考えるとアプリ側できっちり対応する必要がありました。
■アプリをサブディスプレイに対応させる
本体デバイス用のベースUIViewとしてViewForMain、外部ディスプレイ用としてViewForSubというインスタンスがあるとします。
if ([[UIScreen screens] count] >1) {
//スクリーンが2つ以上存在する=外部ディスプレイ有り
UIScreen *secondScreen = [[UIScreen screens] objectAtIndex:1];
UIWindow *secondWindow = [[UIWindow alloc] initWithFrame:[secondScreen bounds]];
secondWindow.screen = secondScreen;
ViewForSub = [[UIView alloc] initWithFrame:[secondScreen bounds]];
ViewForSub.backgroundColor = [UIColor blackColor];
//以下、ViewForSubに必要なUI部品をaddSubviewしていく
//必要に応じて、ViewForMainにUILabel等を置いて「テレビ画面出力中」などと表示する
} else {
//外部ディスプレイ無し
(以下、ViewForMainに必要なUI部品をaddSubviewしていく)
}
[UIScreen screens] cound]でOSが認識しているモニタの数がわかるので、それが1より多い場合はサブモニタがあるということで、UIScreenクラスのsecondScreenオブジェクトに2番目(objectAtIndex:1)を入れ、更にUIWindowsを入れ、UIViewを入れてやります。サイズは全てsecondScreenのものを引き継いでおきます。これで後は普通にUI部品を配置して利用できます(もちろんUIButton等を置いても押せませんが)。
とりあえずこんな感じで外部ディスプレイ側に表示できました。実際には、アプリ起動中にアダプターが挿抜されたのを検知して切換処理をする等の仕組みが必要になりますがここでは割愛。というかまだ未着手…
■全画面で表示されない?
さてそこまではAppleのドキュメントやブログ記事などを参考に辿り着いたのですが、なぜかフルHDモニタに接続した時に全画面表示されずに4辺に黒縁が出てしまう現象が発生。iOSシミュレーター上で仮想1280×720ディスプレイを使っても発生しません。
MPMoviePlayerはもとより、UIWindowsやUISreenインスタンスのbound.sizeを取ってみてもちゃんと1920×1080になっているにも関わらず、です。写真の様にポーズアイコンを座標0,0で置いてみると、動画部分の左上隅に来ます。アプリ的には1920×1080で動画を表示しているつもりっぽい。モニタ側で入力信号情報を表示するとこれまた1920×1080。試しに手動でboundを2000×1200とかにすると黒縁部分が減ります。この数字をつきつめればピッタリ全画面にはできるでしょうがどう考えても拡大->縮小とリサイズが2回起きて無駄だし画質も損なわれるでしょう。MPMoviePlayerの全画面表示系のプロパティをあれこれいじっても解決せず。UIScreenより上の階層で何かが画面を1割くらいスケーリングしてそれを1080pでアダプターに送出しています。
でまぁ足かけ二日ほど悩んだ挙げ句、
secondScreen.overscanCompensation = UIScreenOverscanCompensationInsetApplicationFrame;
で解決できました。オーバースキャンという言葉にもっと早く思い至っていれば検索もヒットさせられたかも知れません。もうアナログ時代の言葉だと思って記憶の底に沈んでましたw。overscanCompensationプロパティには3つの定数があるんですが、なんだか一番全画面っぽくないコイツが勝利の鍵でした。公式ドキュメントはこちら。iOS5からの対応みたいですが、とりあえずiOS4.3シミュレーターではクラッシュなどはしないようですが、iOS4.3の実機だともしかすると全画面化されないままかも知れません。
見事、フルHD画面いっぱいに動画を再生できるようになりました。
今のところ日本語でoverscanCompensationに関して触れている記事はヒットしなそげので、参考に紹介しておきます。