[AS3] FeathersのScreenNavigatorをiOSのUINavigationControllerっぽく使いたい

2013/11/20

こんにちは。きんくまです。

FeathersにScreenNavigatorっていう、画面を切り替えるクラスがあります。
iOSでいうところのUINavigationControllerです。

で、使い方を調べていたのだけど、クラス名を登録して、ScreenNavigatorの方にインスタンス化をお願いするというのがデフォルトの使い方らしいです。

>> How to use the Feathers ScreenNavigator component

でも、自分としては、UINavigationControllerっぽくインスタンス化したのをpushしたいです。で、画面を戻るときはpopしたいです。
ぐぐったところ同じことを考えている人がいました。

>> ScreenNavigator history functionality

で、特にライブラリ側に手をいれないで、ScreenNavigatorを拡張したクラスを作りました。

HistoryScreenNavigator

package feathers.controls
{
	import feathers.controls.PanelScreen;
	import feathers.controls.ScreenNavigator;
	import feathers.controls.ScreenNavigatorItem;
	
	public class HistoryScreenNavigator extends ScreenNavigator
	{
		protected var _poppingScreen:PanelScreen;
		protected var _isTransitionPopping:Boolean = false;
		protected var _history:Vector.<PanelScreen> = new <PanelScreen>[];
		protected var _serialIdName:String = "screenId";
		protected var _serialIdIndex:int = 0;
		
		public function HistoryScreenNavigator()
		{
			super();
		}
		
		public function pushScreen(screen:PanelScreen):void
		{
			screen.name = getCurrentScreenId();
			addScreen(screen.name, new ScreenNavigatorItem(screen));
			_history.push(screen);
			showScreen(getCurrentScreenId());
			countUpSerialIdIndex();
		}
		
		public function popScreen():void
		{
			if(_history.length > 1){
				_poppingScreen = _history.pop();
				_isTransitionPopping = true;
				var prevScreen:PanelScreen = _history[_history.length - 1];
				showScreen(prevScreen.name);
			}	
		}
		
		override protected function transitionComplete():void
		{
			super.transitionComplete();
			if(_isTransitionPopping){
				removeScreen(_poppingScreen.name);
				_poppingScreen.dispose();
				_poppingScreen = null;
				_isTransitionPopping = false;
			}
		}
		
		private function getCurrentScreenId():String
		{
			return _serialIdName + _serialIdIndex;
		}
		
		private function countUpSerialIdIndex():void
		{
			_serialIdIndex++;
		}
	}
}

使い方

pushScreenにPanelScreenのインスタンスを入れて次の画面へすすみます。
popScreen()すると、前の画面に戻ります。

デモ画像
ボタンを押すとポップアップが開いて、画面をスライドする

feathers_slide_fig

サンプルの画面1

package
{
	import feathers.controls.Button;
	import feathers.controls.HistoryScreenNavigator;
	import feathers.controls.PanelScreen;
	import feathers.events.FeathersEventType;
	
	import starling.events.Event;
	
	public class MyScreen1 extends PanelScreen
	{
		private var _nextButton:Button;
		
		public function MyScreen1()
		{
			super();
			addEventListener(FeathersEventType.INITIALIZE, initHandler);
		}
		
		private function initHandler(e:Event):void
		{
			headerProperties.title = "画面その1";
			_nextButton = new Button();
			_nextButton.label = "次へ";
			addChild(_nextButton);
			_nextButton.addEventListener(Event.TRIGGERED, nextButtonTriggeredHandler);
		}
		
		private function nextButtonTriggeredHandler(e:Event):void
		{
			//ownerでScreenNavigatorが参照できる
			var nav:HistoryScreenNavigator = this.owner as HistoryScreenNavigator;
			
			//次の画面のインスタンスを作ってから、pushする
			var nextScreen:MyScreen2 = new MyScreen2();
			nav.pushScreen(nextScreen);
		}
	}
}

サンプルの画面2

package
{
	import feathers.controls.Button;
	import feathers.controls.HistoryScreenNavigator;
	import feathers.controls.PanelScreen;
	import feathers.events.FeathersEventType;
	
	import starling.display.DisplayObject;
	import starling.events.Event;
	
	public class MyScreen2 extends PanelScreen
	{
		private var _backButton:Button;

		public function MyScreen2()
		{
			super();
			addEventListener(FeathersEventType.INITIALIZE, initHandler);
		}
		
		private function initHandler(e:Event):void
		{
			headerProperties.title = "画面その2";
			_backButton = new Button();
			_backButton.label = "前へ";
			_backButton.width = 80;
			_backButton.height = 35;
			headerProperties.leftItems = new <DisplayObject>
			[
					this._backButton
			];
			_backButton.addEventListener(Event.TRIGGERED, backButtonTriggeredHandler);
		}
		
		private function backButtonTriggeredHandler(buttonEvent:Event):void
		{
			//ownerでScreenNavigatorが参照できる
			var nav:HistoryScreenNavigator = this.owner as HistoryScreenNavigator;

			//前の画面へ戻る
			nav.popScreen();
		};
	}
}

FeathersではポップアップはCalloutっていう名前になってました。
メインからはこんな感じに呼び出します。

 
			//ナビゲーション設定
			_nav = new HistoryScreenNavigator();
			_nav.clipContent = true;
			_nav.width = 320;
			_nav.height = 480;
			var screen1:MyScreen1 = new MyScreen1();
			_nav.pushScreen(screen1);
			
			//画面遷移アニメーションの設定
			_transitionManager = new ScreenSlidingStackTransitionManager(_nav);
			_transitionManager.duration = 0.6;
			_transitionManager.ease = Transitions.EASE_IN_OUT;

			//ポップアップの設定
			var callout:Callout = Callout.show(_nav, _startButton);

			//以下の設定をしないと、ボタンを押して画面遷移するときにCalloutが閉じてしまう。
			//毎回書かずに、自作テーマの方に書いておくとよいかも。
			callout.closeOnTouchBeganOutside = true;
			callout.closeOnTouchEndedOutside = false;

自作iPhoneアプリ 好評発売中!
フォルメモ - シンプルなフォルダつきメモ帳
ジッピー電卓 - 消費税や割引もサクサク計算!

ページトップへ戻る