Feathersには画面遷移を行うための、ScreenとScreenNavigator[1]というクラスがある。
Screenが画面そのもので、ScreenNavigator[1]がそれを管理するクラス。
Screenはそのまま使うより、継承して使うことが多い。そして、initializeメソッドをオーバーライドして初期化を行う。
override protected function initialize():void { super.initialize(); //ここで初期化する }
ScreenはSpriteを継承しているので、addChildで描画オブジェクトを付け加えられる。 ScrollScreen[4]やPanelScreen[5]を使うとスクロールしたりヘッダーやフッターをつけた画面も簡単に作れる。
Screen自体は単に画面の大もとになるというだけで、特筆するほどの機能は無い。
ScreenをScreenNavigator[1]に登録すると画面遷移が簡単にできるようになる。 ScreenNavigator[1]への登録はScreenNavigatorItem[8]を使う。
var screenNavigator:ScreenNavigator = new ScreenNavigator(); baseSp.addChild(screenNavigator); var screenNavigatorItem:ScreenNavigatorItem = new ScreenNavigatorItem( new TestScreen1() ); screenNavigator.addScreen( "screen1", screenNavigatorItem );
あとは、
screenNavigator.showScreen("screen1");
とすればそのスクリーンが表示される。この表示される時にScreenのinitializeメソッドが呼ばれる。
ここで注意しないといけないのは、ScreenNavigatorItem[8]はScreenのクラスとインスタンスのどちらかをコンストラクタ引数として取り得ることである。つまり、
new ScreenNavigatorItem( TestScreen1 );
としても、
new ScreenNavigatorItem( new TestScreen1() );
としてもScreenNavigatorItem[8]のインスタンスは作れる。これらは一見同じように動作するが、内部的には異なる動作をする。
クラスを与えたときは、画面遷移のときにdisposeが呼ばれて前のScreenが破棄されメモリが解放される。
インスタンスを与えたときは、そのインスタンスが保持され次回に再利用されるので画面遷移でもdisposeが呼ばれない。
よってメモリを節約したいときはクラスを与えて初期化した方が良い。しかし、画面遷移のたびにdisposeが呼ばれて次にまたインスタンス作成となると非力なモバイル機器ではかなり処理がもたつく。メモリに余裕があるならできるだけインスタンスを与えて初期化した方が良い。
ちなみに私は自動でdisposeが行われないように全てインスタンスで初期化し、自前のdisposeメソッドを作って必要なタイミングに必要なメモリだけ解放している。
ScreenNavigatorItem[8]で便利なのは画面遷移のイベントを設定できることである。つまり、
screenNavigator.setScreenIDForEvent( "screen1Show", "screen1" );
としておくと、ScreenNavigator[1]に登録したスクリーンで
dispatchEventWith("screen1Show");
とすると、screen1のIDの画面へと遷移する。
画面遷移のアニメーションも好みの物に変更できる。たとえばフェイドインなら、
screenNavigator.transition = Fade.createFadeInTransition();
となる。
ScreenNavigator[1]は複数同時に使うことができる。よって、たとえば画面上半分と下半分を別画面のようにして別々に画面遷移する事も可能である。それを使うとたとえばこのゲーム[11]のように、ヘッダーとそれ以外を別々に画面遷移させたりするのが簡単にできる。
Adobe Airでのアプリ制作の弱点の一つとして、インスタンスの作成などの初期化処理がとても遅いことがあげられる。そのため、cocos2d-xなどに比べると画面遷移でアプリがスタックしたようになりやすい。場合によっては数秒ぐらいアプリがとまったように見えるため、ユーザビリティの観点から致命的となる。
これを防ぐには遷移先の画面の初期化が終わるまでロード画面を表示させるというのがある。しかし、初期化中に単純にロードアニメーションを表示させてもそちらも止まってしまうので意味が無い。
ロード画面の表示させかたとしては、一つはWorkerを使って別スレッドでローダーを実行するというのがある。アプリだとこちらが一般的かも知れない。ただ、WorkerはAirでしか使えないのでWebでも公開している私は使っていない。
もう一つはタイマーで初期化を分散する方法である。つまり、まず初期化関数の配列を定義し、
protected var firstInitFunctions:Vector.<Function> = new Vector.<Function>();
それに初期化処理をpushしていく。
firstInitFunctions.push(function():void { //初期化処理1 }); firstInitFunctions.push(function():void { //初期化処理2 }); firstInitFunctions.push(function():void { //初期化処理3 });
これをタイマーで一つずつ実行していく。
protected var firstInitTimerCnt:int = 0; private function onInitTimerChick(e:TimerEvent):void { firstInitFunctions[firstInitTimerCnt](); firstInitTimerCnt++; if (firstInitFunctions.length <= firstInitTimerCnt) { firstInitFunctions.length = 0; //初期化終わり } }
すると処理が分散されるのでローダーのアニメーションはとまらずに実行される。リリースするのがアプリのみならWorkerを使った方が楽かも知れない。
StackScreenNavigator[14]なら画面遷移をスタックしてくれるので、「戻る」処理が必要ならそちらが便利。 詳細はStarling+FeathersでStackScreenNavigator[17]を参照のこと。
(This host) = https://njf.jp