In many rich Internet applications, the interface changes based on the task the user is performing. A simple example is an image that changes when the user rolls the mouse over it. More complex examples include user interfaces whose contents change depending on the user's progress through a task, such as changing from a browse view to a detail view. View states let you easily implement such applications.
At its simplest, a view state defines a particular view of a component. For example, a product thumbnail could have two view states; a base state with minimal information, and a "rich" state with links for more information or to add the item to a shopping cart, as the following figure shows:
To create a view state, you define a base state, and then define a set of changes, or overrides, that modify the base state to define the new view state. Each additional view state can modify the base state by adding or removing child components, by setting style and property values, or by defining state-specific event handlers.
A view state does not have to modify the base state. A view state can specify modifications to any other view state. This lets you create a set of view states that share common functionality while adding the overrides specific to each view state. For more information, see Basing a view state on another view state.
One use of view states is to implement a login and registration form. In this example, the base view state prompts the user to log in, and includes a LinkButton control that lets the user register, if necessary, as the following image shows:
If the user selects the Need to Register link, the form changes view state to display registration information, as the following image shows:
Notice the following changes to the base view state to create this new view state:
When the user clicks the Return to Login link, the view state changes back to base view state to display the Login form, reversing all of the changes made when changing to the register view state.
The following table shows the classes that you use to define view states:
|
Class |
Description |
|---|---|
|
AddChild and RemoveChild |
Adds or removes a child component as part of a change of view state. For more information, see Adding and removing components by using overrides. |
|
SetEventHandler |
Adds an event handler as part of a change of view state. For more information, see Setting overrides on event handlers. |
|
SetProperty |
Sets a component property as part of a change of view state. For more information, see Setting overrides on component properties. |
|
SetStyle |
Sets a style property on a component as part of a change of view state. For more information, see Setting overrides on component styles. |
The base view state of an application or component is the default view state. If you omit any view state specifications, you can consider your application to have a singe view state: the base state. To add additional view states to the base view state, you use the <mx:states> tag. Within the body of the <mx:states> tag, you can add one or more <mx:State> tags, one for each additional view state.
The UIComponent class defines the currentState property that you use to set the view state. In the previous example, you use Button controls to set the currentState property of the Application object to either "NewButton", the name of the view state specified by the <mx:State> tag, or an empty String, "", corresponding to the base view state. When the application starts, the default value of the currentState property is ''.
An application or component can set the initial view state to a non-base view state. To use a view state other than the base state as the initial view state, set the currentState property to the specific view state. Use code such as the following, for example, to specify that a component is initially in its collapsed state:
<myComps:CollapsePanel currentState="collapsed">
The following example creates the Login and Register forms shown in Example: Login form application. This application has the following features:
<?xml version="1.0"?>
<!-- states\LoginExample.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"
verticalAlign="middle">
<!-- The Application class states property defines the view states.-->
<mx:states>
<mx:State name="Register">
<!-- Add a TextInput control to the form. -->
<mx:AddChild relativeTo="{loginForm}"
position="lastChild">
<mx:FormItem id="confirm" label="Confirm:">
<mx:TextInput/>
</mx:FormItem>
</mx:AddChild>
<!-- Set properties on the Panel container and Button control.-->
<mx:SetProperty target="{loginPanel}"
name="title" value="Register"/>
<mx:SetProperty target="{loginButton}"
name="label" value="Register"/>
<!-- Remove the existing LinkButton control.-->
<mx:RemoveChild target="{registerLink}"/>
<!-- Add a new LinkButton control to change view state
back to the login form.-->
<mx:AddChild relativeTo="{spacer1}" position="before">
<mx:LinkButton label="Return to Login"
click="currentState=''"/>
</mx:AddChild>
</mx:State>
</mx:states>
<mx:Panel id="loginPanel"
title="Login"
horizontalScrollPolicy="off"
verticalScrollPolicy="off">
<mx:Form id="loginForm">
<mx:FormItem label="Username:">
<mx:TextInput/>
</mx:FormItem>
<mx:FormItem label="Password:">
<mx:TextInput/>
</mx:FormItem>
</mx:Form>
<mx:ControlBar>
<!-- Use the LinkButton to change to the Register view state.-->
<mx:LinkButton id="registerLink"
label="Need to Register?"
click="currentState='Register'"/>
<mx:Spacer width="100%" id="spacer1"/>
<mx:Button label="Login" id="loginButton"/>
</mx:ControlBar>
</mx:Panel>
</mx:Application>
The executing SWF file for the previous example is shown below:
In this example, you define an application with three Panel containers and three view states, as the following example shows:
To change view state, click on the Panel container that you want to display in the expanded size. For a version of this example that adds a transition to animate the view state change, see Defining transitions.
<?xml version="1.0"?>
<!-- states/ThreePanel.mxml -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" width="400">
<!-- Define the two view states, in addition to the base state.-->
<mx:states>
<mx:State name="One">
<mx:SetProperty target="{p1}" name="x" value="110"/>
<mx:SetProperty target="{p1}" name="y" value="0"/>
<mx:SetProperty target="{p1}" name="width" value="200"/>
<mx:SetProperty target="{p1}" name="height" value="210"/>
<mx:SetProperty target="{p2}" name="x" value="0"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="100"/>
<mx:SetProperty target="{p2}" name="height" value="100"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
<mx:State name="Two">
<mx:SetProperty target="{p2}" name="x" value="110"/>
<mx:SetProperty target="{p2}" name="y" value="0"/>
<mx:SetProperty target="{p2}" name="width" value="200"/>
<mx:SetProperty target="{p2}" name="height" value="210"/>
<mx:SetProperty target="{p3}" name="x" value="0"/>
<mx:SetProperty target="{p3}" name="y" value="110"/>
<mx:SetProperty target="{p3}" name="width" value="100"/>
<mx:SetProperty target="{p3}" name="height" value="100"/>
</mx:State>
</mx:states>
<!-- Define the Canvas container holding the three Panel containers.-->
<mx:Canvas id="pm" width="100%" height="100%">
<mx:Panel id="p1" title="One"
x="0" y="0" width="100" height="100"
click="currentState='One'">
<mx:Label fontSize="24" text="One"/>
</mx:Panel>
<mx:Panel id="p2" title="Two"
x="0" y="110" width="100" height="100"
click="currentState='Two'">
<mx:Label fontSize="24" text="Two"/>
</mx:Panel>
<mx:Panel id="p3" title="Three"
x="110" y="0" width="200" height="210"
click="currentState=''">
<mx:Label fontSize="24" text="Three"/>
</mx:Panel>
</mx:Canvas>
</mx:Application>
The executing SWF file for the previous example is shown below:
View states give you one way to change the appearance of an application or component in response to a user action. You can also use navigator containers, such as the Accordion, Tab Navigator, and ViewStack containers when you perform changes that affect several components.
Your choice of using navigator containers or states depends on your application requirements and user-interface design. For example, if you want to use a tabbed interface, use a TabNavigator container. You might decide to use the Accordion container to let the user navigate through a complex form, rather than using view states to perform this action.
When comparing view states to ViewStack containers, one thing to consider is that you cannot easily share components between the different views of a ViewStack container. That means you will have to recreate a component each time you change views. For example, if you want to show a search component in all views of a View Stack container, you have to define it in each view.
When using view states, you can easily share components across multiple view states by defining the component once, and then including it in each view state. For more information about sharing components among view states, see Adding and removing components by using overrides.
For more information on navigator containers, see Using Navigator Containers.
Consider the following additional techniques for structuring and implementing a state-based applications: