Это на самом деле даже немного грустно, что флекс так извратил идею состояний

На самом деле, то, что вам нужно - это именно состояния, но не то, что под ними подразумевается во флексовом фреймворке. Логика таких состояний примерно следующая: Каждое состояние - отдельный класс, где описывается логика происходящего специфичная только для этого состояния.
Пример:

Код AS3:
<?xml version="1.0" encoding="utf-8"?>
<!-- StatefulApplication.mxml -->
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:states="*"
minWidth="955" minHeight="600">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:applicationComplete>
<![CDATA[
this.theState = this.loggedOut;
this.nextState = this.loggedIn;
this.theState.enter();
]]>
</s:applicationComplete>
<fx:Declarations>
<states:LoggedInState id="loggedIn"/>
<states:LoggedOutState id="loggedOut"/>
</fx:Declarations>
<fx:Script>
<![CDATA[
public var nextState:ApplicationState;
public var previousState:ApplicationState;
public var theState:ApplicationState;
]]>
</fx:Script>
</s:Application>

Код AS3:
package
{
import mx.core.IMXMLObject;
public class ApplicationState implements IMXMLObject
{
protected var _application:StatefulApplication;
public function ApplicationState() { super(); }
public function initialized(document:Object, id:String):void
{
this._application = document as StatefulApplication;
}
public function enter():void { }
public function exit():void
{
this._application.previousState = this;
this._application.theState = this._application.nextState;
this._application.theState.enter();
}
}
}

Код AS3:
package
{
import flash.events.KeyboardEvent;
import flash.events.MouseEvent;
import flash.ui.Keyboard;
import spark.components.Button;
import spark.components.TextInput;
public class LoggedOutState extends ApplicationState
{
private var _input:TextInput;
private var _button:Button;
public function LoggedOutState() { super(); }
public override function enter():void
{
if (!this._input) this.initInput();
if (!this._button) this.initButton();
super._application.addElement(this._input);
super._application.addElement(this._button);
}
public override function exit():void
{
super._application.removeElement(this._button);
super._application.removeElement(this._input);
super._application.nextState = super._application.loggedIn;
super.exit();
}
private function initInput():void
{
this._input = new TextInput();
this._input.width = 300;
this._input.height = 30;
this._input.addEventListener(
KeyboardEvent.KEY_DOWN, this.keyDownHandler);
}
private function initButton():void
{
this._button = new Button();
this._button.width = 200;
this._button.height = 30;
this._button.label = "Login";
this._button.addEventListener(
MouseEvent.CLICK, this.clickHandler);
}
private function logIn():void
{
if (this._input.text) this.exit();
}
private function keyDownHandler(event:KeyboardEvent):void
{
if (event.keyCode == Keyboard.ENTER) this.logIn();
}
private function clickHandler(event:MouseEvent):void
{
this.logIn();
}
}
}

Код AS3:
package
{
import flash.events.MouseEvent;
import mx.controls.Button;
public class LoggedInState extends ApplicationState
{
private var _button:Button;
public function LoggedInState() { super(); }
public override function enter():void
{
if (!this._button) this.initButton();
super._application.addElement(this._button);
}
public override function exit():void
{
super._application.removeElement(this._button);
super._application.nextState = super._application.loggedOut;
super.exit();
}
private function initButton():void
{
this._button = new Button();
this._button.width = 200;
this._button.height = 30;
this._button.label = "Logout";
this._button.addEventListener(
MouseEvent.CLICK, this.clickHandler);
}
private function clickHandler(event:MouseEvent):void
{
this.exit();
}
}
}
Теряется удобство MXML (но если уж очень заморочитйся, то и это все можно описать в нем, но если нужно бысто и сердито, и чтобы у самого код рвотный рефлекс не вызывал, то должно быть нормально

)
Добавлено через 24 часа 47 минут
Для аналогии написал практически то же самое, но с использованием MXML и "родного" флексового механизма стейтов.

Код AS3:
<?xml version="1.0" encoding="utf-8"?>
<!-- StatefulMXMLApplication.mxml -->
<s:Application
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
xmlns:states="*"
minWidth="955" minHeight="600"
applicationComplete="{this.currentState = 'logout'}">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:states>
<s:State name="login"/>
<s:State name="logout"/>
</s:states>
<states:LoggedInMXMLState includeIn="login"/>
<states:LoggedOutMXMLState includeIn="logout"/>
</s:Application>

Код AS3:
<?xml version="1.0" encoding="utf-8"?>
<!-- LoggedInMXMLState.mxml -->
<s:Group
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="400" height="300">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:creationComplete>
<![CDATA[
this._application = super.document as StatefulMXMLApplication;
]]>
</s:creationComplete>
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
private var _application:StatefulMXMLApplication;
]]>
</fx:Script>
<s:Button label="Logout">
<s:click>
<![CDATA[
this._application.currentState = "logout";
]]>
</s:click>
</s:Button>
</s:Group>

Код AS3:
<?xml version="1.0" encoding="utf-8"?>
<!-- LoggedOutMXMLState.mxml -->
<s:Group
xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
xmlns:mx="library://ns.adobe.com/flex/mx"
width="400" height="300">
<s:layout>
<s:VerticalLayout/>
</s:layout>
<s:creationComplete>
<![CDATA[
this._application = super.document as StatefulMXMLApplication;
]]>
</s:creationComplete>
<fx:Script>
<![CDATA[
import mx.core.UIComponent;
private var _application:StatefulMXMLApplication;
]]>
</fx:Script>
<s:TextInput id="username">
<s:keyDown>
<![CDATA[
var event:KeyboardEvent = arguments[0];
if (event.keyCode == Keyboard.ENTER)
this._application.currentState = "login";
]]>
</s:keyDown>
</s:TextInput>
<s:Button label="Login">
<s:click>
<![CDATA[
if (this.username.text)
this._application.currentState = "login";
]]>
</s:click>
</s:Button>
</s:Group>