Pages

August 11, 2008

Flex UI State Transitions

Posted by Jeremy Mitchell
Software applications contain a large number of unique views. A view is comprised of structural elements and content arranged according to the designer / developer's preference (layout) and rendered on the user's screen.

Traditional web applications encapsulate each view within an HTML page. In a static website, the number of views correlates directly with the number of HTML pages. For example, a static HTML website with five HTML pages contains five views.

However, the number of views increases exponentially when dynamic capabilities are introduced into the mix. Dynamic capabilities are typically implemented through the use of server-side scripts (ColdFusion, PHP, JSP, .NET, etc).

Server-side scripts analyze data against a predefined set of rules (logic) and generate the view elements (HTML) accordingly. Data may include database data, web services data, cookie data, etc. Therefore, web applications dependent on data for presentation as well as content are commonly referred to as "data-driven" web applications. As the data grows and the number of rules increase so does the number of unique views.

Asynchronous technologies (AJAX) and DOM manipulation via JavaScript (DHTML) also contribute to the increasing number of views.

Flex applications are no different.

However, within the Flex framework, the term "View" refers to the User Interface (UI) as a whole and represents an aggregate of all visual permutations of an application. This naming convention mirrors the convention adopted by a popular Flex architecture, MVC (model-view-controller).

The "View" is comprised of view components (containers & controls) and each structural (or layout) variance to a view component is referred to as a View State. View States apply to all components (controls or containers) that extend the UIComponent class and consequently inherit the states property. The states property is an array of View States for that view component. With a default value of NULL, components start out with only one state, the base state. The base state is the root state of the component and consists only of the properties, styles, event handlers and children that you've originally defined for the component.

Adding View States involves adding one or more State objects to the states property of the component. Each State object requires a name and optionally the name of another state in which it is based on. Exclusion of the basedOn property will base your new state on the base state.

The purpose of a state is to alter the appearance of a component in response to a user or system-initiated event (i.e. click of a button). Altering the appearance of a component involves the use of overrides via a State. Valid overrides include:
  • AddChild
  • RemoveChild
  • SetEventHandler
  • SetProperty
  • SetStyle
When using MXML to define states, overrides are implied and the override tag is not required.

The following example demonstrates the use of an event handler to change the View State of the Application container:

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">

<!-- Define State -->
<mx:states>
    <mx:State name="newButton">
        <mx:AddChild relativeTo="{h1}" position="firstChild">
            <mx:Button id="buttonNew" label="New Button"/>
        </mx:AddChild>
    </mx:State>
</mx:states>

<!-- Apply State via event handler -->
<mx:Button id="b1" label="Add a Button" click="currentState='newButton'"/>
The transition from one state to another can be visually enhanced by the use of Transitions. Transitions consist of one or more effects grouped together to play when a state change occurs. Like the states property of a component (control or container), the transitions property is also inherited from the UIComponent class and is data-typed as an array of Transition objects.

Each transition is triggered by a change in a component's state as defined in the fromState and toState properties of a Transition object. Valid values include:
  • A state name
  • An empty string representing the base state
  • An asterisk (*) representing a wildcard matching ALL states
As previously mentioned, the purpose of a transition is to map one or more visual effects to one or more state changes.

Effects come in a variety of flavors and as expected extend the Effect class. Effect types include mask effects (MaskEffect class), sound effects (SoundEffect class) and tween effects (TweenEffect class).

Mask effects include:
  • Iris
  • WipeDown
  • WipeLeft
  • WipeRight
  • WipeUp
Tween effects include:
  • Blur
  • Dissolve
  • Fade
  • Glow
  • Move
  • Pause
  • Resize
  • Rotate
  • Zoom
Sound effects allow you to play an MP3 in response to an event.

Effects can be played in isolation, sequentially (one after another) or in parallel (at the same time). Multiple effects require the creation of a composite effect (CompositeEffect class). Variations of a composite effect may include sequential effects, parallel effects or a combination of both. In either scenario, the component to apply the effects must be defined (target component).

Additional control of each effect is provided through the use of the effect properties. Effect properties include duration, alphaFrom, alphaTo, etc. The details of each effect can be found at the Adobe Flex 3 Language Reference.

The following example demonstrates the use of a state transition:

<mx:transitions>
    <mx:Transition id="myTransition" fromState="*" toState="Advanced">
        <mx:Parallel target="{myVBox}">
            <mx:WipeDown duration="2000"/>
            <mx:Dissolve alphaFrom="0.0" alphaTo="1.0" duration="2000"/>
        </mx:Parallel>
    </mx:Transition>
    <mx:Transition id="yourTransition" fromState="Advanced" toState="*">
        <mx:Sequence target="{myButton}">
            <mx:Zoom duration="1000" zoomHeightTo=".9" zoomWidthTo=".9" />
            <mx:Zoom duration="1000" zoomHeightTo="1" zoomWidthTo="1" />
        </mx:Sequence >
    </mx:Transition>
</mx:transitions>
Note that the use of an effect is not limited to a state transition. Effects can be applied to components in the following manner to create behaviors:

<!-- Define Effect -->
<mx:Zoom id="shrink" duration="100" zoomHeightTo=".9" zoomWidthTo=".9" />

<!-- Apply Behavior -->
<mx:Button id="myButton" label="Resize" mouseDownEffect="{shrink}" />
In the previous example, an effect was registered with a trigger (mouseDownEffect) creating a behavior. Trigger + effect = behavior.

As always, the implementation of these Flex features can be achieved via MXML or ActionScript. The decision is yours.