Views and view navigators are new concepts in the framework that allow developers to dynamically create and navigate hierarchical content in their applications. ViewNavigator is a component that manages the dynamic creation and presentation of content views. A view can be thought of as a group of content with an explicit data model and additional functionality to aid in state persistence and user interface integration. ViewNavigator uses a stack metaphor to manage its sets of views, where only the top most view of a stack is visible and active. A developer can use navigator apis such as pushView
and popView
to navigate to a new instance of a view, or return to a previous view.
ViewNavigator will serve as the core navigation model for mobile applications. Mobile UI paradigms are standardizing, and it's common for an app to traverse an application a full view at a time. ViewNavigator will provide this functionality and will also have a built-in ActionBar for presenting contextual UI for the component.
ClassFactory
or the fx:Component
tag.ViewNavigator is very similar to the mx:``ViewStack
container in that it provides the developer the ability to quickly swap content in a specified view area. The biggest difference between these two components is the navigation model employed by each. ViewStack
can only jump between predefined states. While ViewNavigator's content management system allows a developer to dynamically activate any number of views and quickly jump back to previous views in the order they were instantiated by the user. This allows ViewNavigator to automatically create and maintain a navigation history and better represent the navigation model used by most mobile applications. In addition to this, ViewNavigator contains a data model that provides the ability for views to automatically persist their states between activations and application sessions.
Though the use cases for ViewNavigator and states overlap, ViewNavigator shouldn't be considered a replacement for States, but a feature that can live alongside states. Views and states are similar in that they allow the developer to change content on demand, but their use cases don't exactly match up. States is a system concentrating on changing a predefined sub-portion of components and properties at some point in time, where these states are managed by a single logic thread. While on the other hand, Views encourage centralizing all logic and related content into a single component, which is then fully replaced as the application is navigated. Each View can exist on its own and should contain logic specific to the application state it represents. For example, take a mobile contacts application that has two views, a SearchView and InfoView. SearchView has components and functionality for connecting to the contacts directory, searching it and displaying a list of results. InfoView shows a form and only knows how to populate the fields using a contact data object that is passed to it. These views can exist independently, don't share components and run logic specific to their function. Though this could be accomplished with states, the logic would be a bit more convoluted.
Jen is creating a file system manager. The application allows someone to explore the directories on their mobile device. Each view of the application is just a full screen list showing the files and folders of the current directory. To accomplish this, Jen uses a ViewNavigator and a single custom view she created called FolderListView. Her custom view uses the data property of the View to store the file url of the current directory. As a folder is selected, Jen uses the pushView()
api to add a new instance of the FolderListView to the navigator and pass it the file url of the folder selected. Since the data property is automatically stored in memory, when Jen calls popView()
, the previous view of the previous directory is automatically shown in the state it was in when first viewed. By using ViewNavigator and Views, Jen didn't have to write any state management code to set up this simple application.
Bryan is creating an employee database mobile application. He designs his application to consist of two main views, a search view and details view. Using the new View object as his base class, Bryan creates a EmployeeListView component and a DetailsView component. The EmployeeListView contains a List that is populated with all the employees at Bryan's company. When an employee is selected, Bryan pushes a new view into the navigator using ViewNavigator's navigation method. Then Bryan adds a full-screen ViewNavigator to his application with its firstView
property set to SearchView. When the app is launched, the application automatically shows the SearchView. Since Bryan took advantage of the View template properties, the application automatically shows an ActionBar with the title of the current view as the application is navigated.
ViewNavigator can be broken down into two main parts, the action bar and the view content area.
This image shows the two pieces of the ViewNavigator.
The content area is the main group that contains the currently visible view. As views are created, they are dynamically added as children to this group. ViewNavigator also has an ActionBar component integrated into it that is used to display contextual information about the current view. Properties like the title of the view, or the action buttons related to that view can be placed in this bar using apis exposed on View
. There is only one ActionBar instance per view navigator, so this component is shared between all the views. As a view becomes active, it updates the content of the ActionBar.
ViewNavigator will use a stack based approach for managing views. Internally, the navigator will host a vector of view objects, called a navigation stack, where the top most view in the stack is active and visible. ViewNavigator will provide push and pop operations to allow developers to manipulate the stack of views. For example, calling navigator.pushView(``MyView``)
would tell the navigator to create and add a new view onto the navigation stack, and then display it. While calling navigator.popView()
would cause the navigator to destroy the current view and then recreate and display the previous one on the stack. This allows the developer to dynamically navigate through content in their application.
The top most view is always the active and visible view. ViewNavigator doesn't provide a mechanism to allow a developer to select and display a specific View on the navigation stack.
In the above example, an application starts off displaying a Search view. When the user selects a user, the Details view is pushed onto the navigation stack. This will cause the Search view to be removed and destroyed, while the Details view becomes the new visible and active view.
ViewNavigator will dynamically create views as they become visible. This means developers will be passing Class objects to the various navigation operations (i.e pushView), and not view instances or ClassFactory objects. A developer can always pop back to the first view in the navigator by calling popToFirstView()
. In addition, a developer can pop all views from a navigator. When the navigation stack is empty, no view will be displayed, but the navigator should still operate. See #API Description for more information.
Below is an example of how a ViewNavigator might be defined in MXML:
<s:ViewNavigator id="navigator" width="100%" height="100%" firstView="MainView"/>
This will create a navigator that initially creates an instance of MainView to serve as its first visible view. ViewNavigator does not support adding children to its MXML tag, meaning you cannot add visual components to the ViewNavigator MXML tag.
Paged-view and swipe view navigation will not be supported by ViewNavigator. This use case can be accomplished by using a List or by writing a custom ViewNavigator.
View
is the base class for all views created for an application, and will be a subclass of Group
. A view can be thought of as a standard Flex 4 ItemRenderer with an integrated data model and additional functionality that allows a view to provide contextual information about itself to external components (such as ActionBar). A view will have a data
property that can be used to represent the content and the state of the view. This object is automatically serialized, persisted and restored by the view's navigator as the view is activated and deactivated.
View
will expose a set of properties that provide contextual information that can be optionally displayed by external components.
Properties related to ActionBar
Property
Description
title
The title of the view which is display in the ActionBar's title area
titleContent
The UI components that should be displayed inside the ActionBar's content area.
titleLayout
The layout of the content group that is holding the view's titleContent
navigationContent
The UI components that should be displayed inside the ActionBar's navigation content area.
navigationLayout
The layout of the action bar's navigation content group
actionContent
The UI components that should be displayed inside the ActionBar's action content area
actionLayout
The layout of the content group presenting the action content
All of the the ActionBar properties above, also exist on ViewNavigator
. This allows the navigator to define default values for these properties.
Properties related to ViewNavigator
Property
Description
actionBarVisible
Indicates whether the view wants the action bar visible or not
overlayControls
Indicates whether the navigator's action bar should hover on top of the view content area
destructionPolicy
Sets the destruction policy of a view
The initial implementation of ViewNavigator will only allow one view to be visible at a time. As a new view becomes active, the UI components for the previous view are destroyed. This allows Flex applications to better conserve memory when using a ViewNavigator. But in some situations, it is too expensive to destroy and recreate views as the user navigates through the application. To deal with this situation, Views will have a destructionPolicy
property that determines what should happen when the view is replaced on the stack. By default, this will be set to ContainerDestructionPolicy``.AUTO
, meaning that views should be destroyed immediately after removal. If set to ContainerDestructionPolicy``.NEVER
, the view will remain in memory. This property is useful to use if a developer knows that a view takes a particularly long time to instantiate or if the developer doesn't want to lose the content in the views.
Views will support data persistence through the use of a data object. This object is set to the data
parameter of the pushView() api call. A view is guaranteed to have its data property properly set before it is added to the display list. A view's data property is automatically saved when a new view is pushed on top of it. This same object will be restored when the view is re-instantiated and activated. This allows the developer to maintain state information of a view at runtime.
Sometimes a developer will want to use a generic view to handle multiple use cases. For example, the developer may create a simple employee detail view that displays slightly different controls and information when pushed by different views. To accomplish this, the ViewNavigator``.pushView
method will take an optional context
parameter. This parameter can be any string the developer chooses, and will be assigned to the View.context
property when created. At creation time, a view can check its context property and execute custom logic based on its value. This property is guaranteed to be set by the time the FlexEvent``.ADD
event is received on the view.
When a view is popped from the stack, it is automatically destroyed by the framework. Before this happens, a view has the option of returning data to the view that will become active. If a view wants to return data when removed, it can override its createReturnObject()
method to generate a proper return value. The ViewNavigator will save this object internally, and the new view can access it from with the navigator.returnedObject
property. The property is a ViewReturnObject which contains the object that was returned and the context in which the removed view was pushed (See #Setting the View Context). ViewNavigator``.poppedViewReturnedObject
is guaranteed to be set by the time the new view receives the add
event and will be destroyed after the view receives its viewActivate
event.
Note, the return object is only stored when a view is popped of the navigation stack or replaced through the use of the pop and replace navigation operations (e.g., replaceView
, popView
, etc…). It will be cleared after the new view receives its ViewNavigatorEvent.VIEW_ACTIVATE event.
ViewNavigator uses the standard flex invalidation scheme to manage the process behind transitioning to a new view. This means that a developer can make multiple navigation operations in a single frame without the runtime wastefully creating the needed views and objects for each call. When a validation pass begins on the navigator, it grabs the top most view object on the navigation stack and transitions from its current view to the new one. All navigation operations that happened in-between are not visually shown. In addition, a view can cancel a navigation operation by canceling its FlexEvent.REMOVING event.
Below is flow chart describing the events and main actions that are completed when the developer requests a new view to become visible.
Events dispatched by View
FlexEvent``.ADD
: Dispatched when a view is added to the display list.FlexEvent``.REMOVE
: Dispatched when a view is removed from the display list.ViewNavigatorEvent``.REMOVING
: Dispatched by a view when it is about to be removed. Canceling this event will prevent the navigator from changing the view.ViewNavigatorEvent``.VIEW_ACTIVATE
: Dispatched when a view has been activated.ViewNavigatorEvent``.VIEW_DEACTIVATE
: Dispatched when a view has been deactivated.Events dispatched by ViewNavigator
ElementExistenceEvent``.ELEMENT_ADD
: Dispatched when a view has been added to the display list. This method is dispatched BEFORE the view dispatches FlexEvent``.ADD
. The index
property of the event should be ignored because it doesn't necessarily represent the elements location in the navigation stack.ElementExistenceEvent``.ELEMENT_REMOVE
: Dispatched when a view has been removed from the display list. This method is dispatched BEFORE the view dispatches FlexEvent``.REMOVE
. The index
property of the event should be ignored because it doesn't necessarily represent the elements location in the navigation stack.All view navigation operations are cancelable. When a navigation operation is called, the active view will receive a removing
event (ViewNavigatorEvent``.REMOVING
). If the developer calls preventDefault()
on this event, the navigation operation is canceled. Cancelable navigation operations are listed below:
pushView()
popView()
popToFirstView()
popAll()
replaceView()
ViewNavigator will allow developers to switch between two predefined layout modes for the action bar inside the navigator. These layouts impact the way the ActionBar and the content group are laid out during execution of the application. The developer will be able to switch between these by using the overlayControls
property on View
and ViewNavigator
. When overlayControls
is false, the ActionBar and the content area are laid out with a standard vertical layout structure. When true, the view content area spans the entire width and height of the navigator while the ActionBar hovers on top of the content area with an alpha value applied.
Changing the overlay mode also changes the state of the navigator's standard skin. When overlayControls
is true, "AndOverlay" is appended to the current states name. For example, ViewNavigator's skin is in the "portrait" state by default. When overlayControls
is set to true, the navigator's skin's state is changed to "portraitAndOverlay".
This image shows the different overlay modes ViewNavigator supports
The navigator's control bars can be hidden and shown by both the navigator and the view. ViewNavigator will expose showActionBar()
and hideActionBar()
methods to allow an application to toggle the visibility of the action bar. A view also has a actionBarVisible
property that controls whether a the action bar is displayed. Default values for these properties can be set to indicate whether these bars should be visible when a view is created. For example:
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="Image View"
actionBarVisible="false">
<s:Scroller width="100%" height="100%">
<s:Group>
<s:BitmapImage source="@Embed('images/img.jpeg')"/>
</s:Group>
</s:Scroller>
<s:Button label="Toggle ActionBar" click="{actionBarVisible = !actionBarVisible}"/>
</s:View>
The code snippet above defines a view that hides the action bar when first created. When the "Toggle ActionBar" button is pressed, the action bar's visibility is toggled. The values stored in actionBarVisible
are not persisted when the navigator navigates away from a view unless that View's destruction policy is set to "none".
It is important to note that when the ViewNavigator hides the action bar, it sets the bar's includeInLayout
and visible
properties to false. When the bar becomes visible, these properties are restored to their original values.
Customizing the Hide and Show Effects
The animation played when the action bar is hidden and shown is controlled by the navigator. A developer can change these by extending ViewNavigator and overriding the proper methods. When customizing the hide and show animations, keep in mind that it is the developers responsibility to animate the actionBar
and contentGroup
skinparts if they exist. When a show or hide request is received by the navigator, the action is queued for the next frame.
To change the default transition, the developer can override the createActionBarHideEffect()
and createActionBarShowEffect()
methods. These functions returns an IEffect
that will automatically be played by the navigator. As stated above, it is important that the visible and includeInLayout property of the ActionBar is set to false after a custom hide animation. See the #API Description for more information.
Views and ViewNavigator will also support portrait and landscape orientations. For a view to display different content in each orientation state, it must define "portrait" and "landscape" states. If these states exist, ViewNavigator will automatically switch the view's state as the device's orientation changes.
Supporting these two features will require the use of the following skin states on ViewNavigator:
When using with ViewNavigatorApplication, the application will automatically orient the navigator to match the device's orientation.
The developer will have the ability to define a transition to be played when the current view is changed. A developer can pass a ViewTransition object to a navigation function to indicate what transition to play when it executes. See the #API Description for more information.
The details behind ViewTransitions are available in the View Transitions spec.
When a view is added and activated by the navigator, a couple of things are done to maintain proper focus on the stage. If the stage's focus is null or the focused object is no longer on the display list, focus is set to the newly activated view. If there is no active view, focus is set to the navigator. In all other situations, the stage focus is considered valid and isn't changed. Changes to focus are executed right before the active view receives its viewActivate
event.
This feature introduces a couple of new events in FlexEvent.
package mx.events
{
class FlexEvent extends Event
{
/**
* Dispatched when the back key is pressed. A cancelable event. If
* canceled, the navigator's default back logic will not be run.
*/
public static const BACK_KEY_PRESSED:String = "backKeyPressed";
/**
* Dispatched when the menu key is pressed. A cancelable event. If
* canceled, the navigator's default menu logic will not be run.
*/
public static const MENU_KEY_PRESSED:String = "menuKeyPressed";
}
}
package spark.events
{
import flash.events.Event;
/**
* The ViewNavigatorEvent class represents event objects dispatched by the
* View class.
*/
public class ViewNavigatorEvent extends Event
{
//--------------------------------------------------------------------------
//
// Class constants
//
//--------------------------------------------------------------------------
/**
* The <code>ViewNavigatorEvent.REMOVING</code> constant defines the value of the
* <code>type</code> property of the event object for an <code>removing</code>
* event. This event is dispatched when a screen is about to be replaced by
* another screen through a navigator action. If <code>preventDefault()</code>
* is called on this event, the view removal will be canceled.
*/
public static const REMOVING:String = "removing";
/**
* The <code>ViewNavigatorEvent.VIEW_ACTIVATE</code> constant defines the value of the
* <code>type</code> property of the event object for an <code>viewActivate</code>
* event. This event is dispatched when a component is activated.
*/
public static const VIEW_ACTIVATE:String = "viewActivate";
/**
* The <code>ViewNavigatorEvent.VIEW_DEACTIVATE</code> constant defines the value of the
* <code>type</code> property of the event object for an <code>viewDeactivate</code>
* event. This event is dispatched when a component is deactivated.
*/
public static const VIEW_DEACTIVATE:String = "viewDeactivate";
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @param type The event type; indicates the action that caused the event.
*
* @param bubbles Specifies whether the event can bubble up
* the display list hierarchy.
*
* @param cancelable Specifies whether the behavior
* associated with the event can be prevented.
*
* @param action The navigation action committed by the view navigator
* that resulted in the event.
*/
public function ViewNavigatorEvent(type:String, bubbles:Boolean = false,
cancelable:Boolean = false,
action:String = null);
//----------------------------------
// action
//----------------------------------
/**
* The navigation action committed by the view navigator that resulted
* in the event.
* Possible actions include a view being activated or deactivated.
*/
public var action:String;
}
}
View is the base class for all views. Developers should use this as their base class for their custom views.
package spark.components
{
//--------------------------------------
// SkinStates
//--------------------------------------
/**
* The skin state used when the view is in portrait orientation
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
<a href="SkinState%28%26quot%3Bportrait%26quot%3B%29">SkinState("portrait")</a>
/**
* The skin state used when the view is in landscape orientation
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
<a href="SkinState%28%26quot%3Blandscape%26quot%3B%29">SkinState("landscape")</a>
//--------------------------------------
// Events
//--------------------------------------
/**
* Dispatched when the back key is pressed when a view exists inside
* a mobile application.
*/
<a href="Event%28name%3D%26quot%3BbackKeyPressed%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="backKeyPressed", type="mx.events.FlexEvent")</a>
/**
* Dispatched when the <code>data</code> property changes.
*/
<a href="Event%28name%3D%26quot%3BdataChange%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="dataChange", type="mx.events.FlexEvent")</a>
/**
* Dispatched when the menu key is pressed when a view exists inside
* a mobile application.
*/
<a href="Event%28name%3D%26quot%3BmenuKeyPressed%26quot%3B%2C%20type%3D%26quot%3Bmx.events.FlexEvent%26quot%3B%29">Event(name="menuKeyPressed", type="mx.events.FlexEvent")</a>
/**
* Dispatched when the current view has been activated.
*/
<a href="Event%28name%3D%26quot%3BviewActivate%26quot%3B%2C%20type%3D%26quot%3Bspark.events.ViewNavigatorEvent%26quot%3B%29">Event(name="viewActivate", type="spark.events.ViewNavigatorEvent")</a>
/**
* Dispatched when the current view has been deactivated.
*/
<a href="Event%28name%3D%26quot%3BviewDeactivate%26quot%3B%2C%20type%3D%26quot%3Bspark.events.ViewNavigatorEvent%26quot%3B%29">Event(name="viewDeactivate", type="spark.events.ViewNavigatorEvent")</a>
/**
* Dispatched when the screen is about to be removed in response
* to a screen change. Calling <code>preventDefault()</code>
* while handling this event will cancel the screen change.
*/
<a href="Event%28name%3D%26quot%3Bremoving%26quot%3B%2C%20type%3D%26quot%3Bspark.events.ViewNavigatorEvent%26quot%3B%29">Event(name="removing", type="spark.events.ViewNavigatorEvent")</a>
class View extends SkinnableContainer implements IDataRenderer
{
//-----------------------------------------------------------
//
// Properties
//
//-----------------------------------------------------------
/**
* Flag indicating whether the current view is active.
*
* @default false
*/
public function get isActive():Boolean;
/**
* The string that describes the context in which this view was
* created. This property is assigned to the <code>context</code>
* parameter that is passed into <code>ViewNavigator.pushView()</code>.
*
* @default null
*
* @see spark.components.ViewNavigator
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function get context():String
/**
* The data object for the view.
*
* @default null
*/
public function get data():Object;
public function set data(value:Object):void;
/**
* Stores the destruction policy of the view. If set to
* "auto", the view is automatically destroyed as new views
* are added. If set to "none", the view instance remains
* in memory.
*
* @default "auto"
*/
<a href="Inspectable%28category%3D%26quot%3BGeneral%26quot%3B%2C%20enumeration%3D%26quot%3Bauto%2Cnever%26quot%3B%2C%20defaultValue%3D%26quot%3Bauto%26quot%3B%29">Inspectable(category="General", enumeration="auto,never", defaultValue="auto")</a>
public function get destructionPolicy():String;
public function set destructionPolicy(value:String):void;
/**
* A reference to the ViewNavigator the view lives in.
*
* @default null
*/
public function get navigator():ViewNavigator;
/**
* Determines the way the navigator's control bars should be
* laid out. If true, the controls hover on top of the current
* view. If false, the components will follow a standard
* vertical layout.
*
* @default false
*/
public function get overlayControls():Boolean;
public function set overlayControls(value:Boolean):void
//----------------------------------------------------------
//
// Template Properties
//
//----------------------------------------------------------
/**
* Flag indicating whether a view should show the action bar or not.
*
* @default true
*/
public function get actionBarVisible():Boolean;
public function set actionBarVisible(value:Boolean):void;
/**
* An array of VisualElements that the current view would like
* displayed in the ActionBar's action content area.
*
* @default null
*/
public function get actionContent():Array;
public function set actionContent(value:Array):void;
/**
* The layout the view would like assigned to the ActionBar's
* action content group.
*
* @default HorizontalLayout
*/
public function get actionLayout():LayoutBase;
public function set actionLayout(value:LayoutBase):void;
/**
* An array of VisualElements that the current view would like
* displayed to the ActionBar's navigation content area.
*
* @default null
*/
public function get navigationContent():Array;
public function set navigationContent(value:Array):void;
/**
* The layout the view would like assigned to the ActionBar's
* navigation content group.
*
* @default HorizontalLayout
*/
public function get navigationLayout():LayoutBase;
public function set navigationLayout(value:LayoutBase):void;
/**
* The title of the view. This string is displayed in the
* ActionBar's content group area if the titleContent property
* isn't set.
*
* @default
*/
public function get title():String;
public function set title(value:String):void;
/**
* An array of VisualElements that the current view would like
* added to the ActionBar's title content area. If this is
* null, the ActionBar will display the title of the view.
*
* @default null
*/
public function get titleContent():Array;
public function set titleContent(value:Array):void;
/**
* The layout the view would like assigned to the ActionBar's
* title content group.
*
* @default HorizontalLayout
*/
public function get titleLayout():LayoutBase;
public function set titleLayout(value:LayoutBase):void;
//-----------------------------------------------------------
//
// Methods
//
//-----------------------------------------------------------
/**
* Methods creates an object that should be returned to the
* previous screen when this view is popped off a navigator's
* stack.
*
* @return null
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function createReturnObject():Object;
/**
* Returns the name of the state to be applied to the view.
* By default, this method will return "portrait" if a portrait
* state is defined and the stage orientation is also portrait.
* "landscape" is returned if the view has defined a landscape
* state and the device is also in a landscape orientation.
* Otherwise null is returned.
*
* @param isLandscape Indicates whether that application is
* currently in a landscape orientation.
*
* @return null
*/
public function getCurrentViewState(isLandscape:Boolean):String;
}
}
This class is used to set the destructionPolicy of the View and ViewNavigator classes. When used on a View, it determines whether the view instance should be deleted when another view is pushed on top of it.
package spark.core
{
/**
* The ContainerDestructionPolicy class defines the constant values
* for the <code>destructionPolicy</code> property of spark view
* classes.
*/
public final class ContainerDestructionPolicy
{
//--------------------------------------------------------------------------
//
// Class constants
//
//--------------------------------------------------------------------------
/**
* The lifespan of the container's children will automatically
* be managed by the container based on the container's own
* heuristic. The default implementation mimics that behavior of
* <code>ContainerDestructionPolicy.ALWAYS</code>
*/
public static const AUTO:String = "auto";
/**
* The container will never destroy its children.
*/
public static const NEVER:String = "never";
}
}
This is the base class for all ViewNavigator.
package spark.components.supportClasses
{
//--------------------------------------
// Events
//--------------------------------------
/**
* The ViewNavigatorBase class defines the base class logic and
* interface used by view navigators. This class contains
* methods and properties related to view management, as well
* as integration points with ViewNavigatorApplicationBase application
* classes.
*/
public class ViewNavigatorBase extends SkinnableContainer
{
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
/**
* Flag indicating whether the navigator is active. The parent navigator
* will automatically set this flag to true or false as its state changes.
*
* @default true
*/
public function get isActive():Boolean;
/**
* The currently active view of the navigator. Only one view can
* be active at a time.
*
* @default null
*/
public function get activeView():View;
/**
* Returns the icon that should be used when this navigator is represented
* by a visual component.
*
* @default null
*/
public function get icon():Object;
public function set icon(value:Class):Object;
<a href="Bindable">Bindable</a>
/**
* The label to be used when this stack is represented by a visual component.
*
* @default null
*/
public function get label():String;
public function set label(value:String):void;
/**
* The last action performed by the navigator.
*
* @default ViewNavigatorAction.NONE
*/
public function get lastAction():String;
/**
* Flag indicates how the navigator's ui controls should be
* laid out in relation to the active view. If true, the view
* will extend the entire content area of the component, and the
* ui controls will hover on top.
*
* Changing this property will result in a skin validation.
*
* @default true
*/
public function get overlayControls():Boolean;
public function set overlayControls(value:Boolean):void;
/**
* The parent navigator for this navigator. This is only used
* if a navigator exists as a child of another navigator.
*
* @default null
*/
public function get parentNavigator():ViewNavigatorBase;
/**
* Flag indicating whether transitions are played by the
* navigator when a view changes or when the actionBar or tab bar
* visibility changes.
*
* @default true
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function get transitionsEnabled():Boolean;
public function set transitionsEnabled(value:Boolean):void;
//--------------------------------------------------------------------------
//
// Public Methods
//
//--------------------------------------------------------------------------
/**
* This method updates various properties of the navigator when a
* new view is added and activated.
*
* @param view The view that was added
*/
public function updateControlsForView(view:View):void;
}
}
package spark.components.supportClasses
{
/**
* The ViewNavigatorAction class defines the constant values
* for the <code>lastAction</code> property of ViewNavigator.
* It indicates what the last committed operation was.
*/
public final class ViewNavigatorAction
{
//--------------------------------------------------------------------------
//
// Class constants
//
//--------------------------------------------------------------------------
/**
*
*/
public static const NONE:String = "none";
/**
*
*/
public static const PUSH:String = "push";
/**
*
*/
public static const POP:String = "pop";
/**
*
*/
public static const POP_ALL:String = "popAll";
/**
*
*/
public static const POP_TO_FIRST:String = "popToFirst";
/**
*
*/
public static const REPLACE_VIEW:String = "replaceView";
/**
*
*/
public static const REPLACE_STACK:String = "replaceStack";
}
}
This is the api exposed by ViewNavigator.
package spark.components
{
<a href="DefaultProperty%28%26quot%3BnavigationStack%26quot%3B%29">DefaultProperty("navigationStack")</a>
//--------------------------------------
// SkinStates
//--------------------------------------
/**
* The state used when the navigator is in portrait orientation
*/
<a href="SkinState%28%26quot%3Bportrait%26quot%3B%29">SkinState("portrait")</a>
/**
* The state used when the navigator is in landscape orientation
*/
<a href="SkinState%28%26quot%3Blandscape%26quot%3B%29">SkinState("landscape")</a>
/**
* The state used when the navigator is in portrait orientation
* and the navigator controls are overlaid on top.
*/
<a href="SkinState%28%26quot%3BportraitAndOverlay%26quot%3B%29">SkinState("portraitAndOverlay")</a>
/**
* The state used when the navigator is in landscape orientation
* and the navigator controls are overlaid on top.
*/
<a href="SkinState%28%26quot%3BlandscapeAndOverlay%26quot%3B%29">SkinState("landscapeAndOverlay")</a>
/**
* The ViewNavigator component is a container that consists of a collection of
* View objects, where only the top most view is visible and active. Views can
* be added and removed by using the popView() and pushView() methods on the
* navigator.
*
* When a new view becomes active, the old view's instance is destroyed.
* When a view is pushed on top of navigator's stack, the old view's data
* property is automatically persisted and restored when it is reactived
* through one of the pop methods.
*
* ViewNavigator doesn't provide index information about the Views that
* it is currently managing and strictly follows a stack navigation model.
* Jumping between a set of views similar to a ViewStack is not supported
* by this component.
*
* ViewNavigator displays an optional action bar that displays contextual
* information defined by the active view. When the active view changes, the
* action bar is automatically updated.
*/
public class ViewNavigator extends ViewNavigatorBase
{
//--------------------------------------------------------------------------
//
// Skin Parts
//
//--------------------------------------------------------------------------
/**
* A skin part that defines the action bar of the navigator.
*/
<a href="SkinPart%28required%3D%26quot%3Bfalse%26quot%3B%29">SkinPart(required="false")</a>
public var actionBar:ActionBar;
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
/**
* The string that describes the context in which the current view was
* created. This property is assigned to the <code>context</code>
* parameter that is passed into <code>ViewNavigator.pushView()</code>.
*
* @default null
*
* @see spark.components.ViewNavigator
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function get context():Object;
/**
* This property is the object to use to initialize the first view
* of the stack. This must be a class that extends <code>View</code>.
*
* @default null
*/
public function get firstView():Class;
public function set firstView(value:Class):void;
/**
* This is the initialization data to pass to the first view when the
* navigator is initialized.
*
* @default null
*/
public function get firstViewData():Object;
public function set firstViewData(value:Object):void;
/**
* Returns the number of views being managed by the navigator.
*/
public function get length():int;
/**
* Holds the return object returned by the last view that was popped
* off the navigation stack. This object is only available when the
* navigator is in the process of switching views in response to a
* pop navigation operation.
*
* <p>This object is guarenteed to be valid when the a view receives
* the <code>FlexEvent.ADD</code> event, and is destroyed after
* the view receives a <code>ViewNavigatorEvent.VIEW_ACTIVATE</code> event.</p>
*
* @default null
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function get poppedViewReturnedObject():ViewReturnObject
//--------------------------------------------------------------------------
//
// UI Template Properties
//
//--------------------------------------------------------------------------
<a href="ArrayElementType%28%26quot%3Bmx.core.IVisualElement%26quot%3B%29">ArrayElementType("mx.core.IVisualElement")</a>
/**
* Array of visual elements that are used as the ActionBar's
* actionContent when a view doesn't define any.
*
* @default null
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function get actionContent():Array;
public function set actionContent(value:Array):void;
/**
* The default layout for the ActionBar's action content group if
* the view doesn't define one.
*
* @default null
*/
public function get actionLayout():LayoutBase;
public function set actionLayout(value:LayoutBase):void;
<a href="ArrayElementType%28%26quot%3Bmx.core.IVisualElement%26quot%3B%29">ArrayElementType("mx.core.IVisualElement")</a>
/**
* Array of visual elements that are used as the ActionBar's
* navigationContent when a view doesn't assign any.
*
* @default null
*/
public function get navigationContent():Array;
public function set navigationContent(value:Array):void;
/**
* The default layout for the ActionBar navigation content group if
* a view doesn't define one.
*
* @default null
*/
public function get navigationLayout():LayoutBase;
public function set navigationLayout(value:LayoutBase):void;
<a href="Bindable">Bindable</a>
/**
* The default title that should be used by the ActionBar if the
* view doesn't provide one.
*
* @default null
*/
public function get title():String;
public function set title(value:String):void;
<a href="ArrayElementType%28%26quot%3Bmx.core.IVisualElement%26quot%3B%29">ArrayElementType("mx.core.IVisualElement")</a>
/**
* Array of visual elements that are used as the ActionBar's
* titleContent when a view doesn't define one.
*
* @default null
*/
public function get titleContent():Array;
public function set titleContent(value:Array):void;
/**
* Layout for the ActionBar's titleContent group.
*
* @default null
*/
public function get titleLayout():LayoutBase;
public function set titleLayout(value:LayoutBase):void;
//--------------------------------------------------------------------------
//
// Public Methods
//
//--------------------------------------------------------------------------
/**
* Removes all of the views from the navigator. This will transition
* the current view to a blank screen.
*
* @param transition The view transition to play
*/
public function popAll(transition:ViewTransition = null):void;
/**
* Pops the top view off the navigation stack.
*
* @param transition The view transition to play
*/
public function popView(transition:ViewTransition = null):void;
/**
* Removes all views except the bottom one from the navigation stack.
*
* @param transition The view transition to play
*/
public function popToFirstView(transition:ViewTransition = null):void;
/**
* Pushes a new view to the top of the navigation stack.
*
* @param viewClass The class used to create the view
* @param data The data object to pass to the view
* @param context An arbitrary object that can be used to describe the context
* of the push. When the new view is created, it will be able to reference
* this property.
* @param transition The view transition to play
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function pushView(viewClass:Class,
data:Object = null,
context:Object = null,
transition:ViewTransition = null):void;
/**
* Replaces the top view of the navigation stack with a View.
*
* @param viewClass The class used to create the view
* @param data The data object to pass to the view
* @param context An arbitrary object used to describe the context
* of the push. When the new view is created, it will be
* able to reference this property.
* @param transition The view transition to play
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function replaceView(viewClass:Class,
data:Object = null,
context:Object = null,
transition:ViewTransition = null):void;
/**
* Shows the action bar.
*
* @param animate Indicates whether a show effect should be played.
*/
public function showActionBar(animate:Boolean = true):void;
/**
* Hides the action bar.
*
* @param animate Indicates whether a hide effect should be played.
*/
public function hideActionBar(animate:Boolean = true):void;
//--------------------------------------------------------------------------
//
// Protected Methods
//
//--------------------------------------------------------------------------
/**
* Commits the navigation operations that have been executed
* on the navigator and begins the view change process.
*/
protected function commitNavigatorAction():void;
/**
* Initializes the view change process by disabling inputs on the
* navigator. If the navigator has a parent, the parents mouse
* interaction flags are disabled.
*/
protected function committingNavigatorAction():void;
/**
* Creates the effect to play when the ActionBar is hidden.
* The produced effect is responsible for animating both the
* actionBar and the contentGroup of the navigator.
*
* @return An effect to play when the ActionBar is hidden
*/
protected function createActionBarHideEffect():IEffect;
/**
* Creates the effect to play when the actionBar is hidden.
* The produced effect is responsible for animating both the
* actionBar and the contentGroup of the navigator.
*
* @return An effect to play when the ActionBar is shown
*/
protected function createActionBarShowEffect():IEffect;
/**
* This method is responsible for completing a view change validation pass.
* It is responsible for cleaning up and destroying the old view, as well as
* activating the new one.
*
* If a transition was played, this method is called after the transition
* completes.
*/
protected function navigatorActionCommitted():void;
}
}
package spark.components.supportClasses
{
/**
* The ViewReturnObject class encapsulates the return value of a view
* when it is popped off a navigation stack. The object contains a reference
* to the returned object as well as the context in which the popped view was
* created. The context is an arbitrary object that is passed as part of the
* <code>ViewNavigator.pushView()</code> method.
*
* @see spark.components.View
* @see spark.components.ViewNavigator#pushView
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public class ViewReturnObject
{
//--------------------------------------------------------------------------
//
// Constructor
//
//--------------------------------------------------------------------------
/**
* Constructor.
*
* @param object The returned object
* @param context The context in which the owner was created
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function ViewReturnObject(object:Object, context:String);
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
//----------------------------------
// object
//----------------------------------
/**
* The return object generated by the view that is being removed.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public var object:Object = null;
//----------------------------------
// context
//----------------------------------
/**
* The context identifier passed to the popped view when it was pushed
* onto the navigation stack.
*
* @see spark.components.ViewNavigator#pushView
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public var context:String = null;
}
}
The following classes are private to the implementation details of ViewNavigator and related features .
This is a data structure that manages the stack of views used by a navigator.
package spark.components.supportClasses
{
import flash.utils.IExternalizable;
/**
* The NavigationStack class is a data structure that is internally used by
* ViewNavigator to track the current set of views that are being managed
* by the navigator.
*/
public class NavigationStack implements IExternalizable
{
//--------------------------------------------------------------------------
//
// Properties
//
//--------------------------------------------------------------------------
/**
* Returns the length of the stack.
*/
public function get length():int;
//--------------------------------------------------------------------------
//
// Methods
//
//--------------------------------------------------------------------------
/**
* Clears the entire stack.
*/
public function clear():void;
/**
* Adds a view to the top of the navigation stack.
*
* @param factory The class of the View to create.
* @param data The data object to pass to the view when it is created
* @param context The context identifier to pass to the view when created
*
* @return The data structure that represents the current view.
*/
public function pushView(factory:Class, data:Object, context:String = null): ViewDescriptor;
/**
* Removes the top view off the stack.
*
* @return The data structure that represented the View.
*/
public function popView():ViewDescriptor;
/**
* Removes all but the root object from the navigation stack.
*
* @return The data structure that represented the View.
*/
public function popToFirstView(): ViewDescriptor;
}
}
package spark.components.supportClasses
{
import flash.utils.IDataInput;
import flash.utils.IDataOutput;
import flash.utils.IExternalizable;
import flash.utils.getDefinitionByName;
import flash.utils.getQualifiedClassName;
import spark.components.View;
/**
* The ViewDescriptor object is a data structure used to store information
* about a view that is being managed by a ViewNavigator.
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public class ViewDescriptor implements IExternalizable
{
/**
* Constructor.
*
* @param viewClass The class used to create the View
* @param data The data object to pass to the view when created
* @param context The context of the view
* @param instance A reference to the instance of the View
*
* @langversion 3.0
* @playerversion Flash 10.1
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public function ViewDescriptor(viewClass:Class = null,
data:Object = null,
context:Object = null,
instance:View = null);
/**
* The string that describes the context in which this view was
* created. This property is assigned to the <code>context</code>
* parameter that is passed into <code>ViewNavigator.pushView()</code>.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public var context:Object;
/**
* The current data object that is being used by the view. When a view
* is removed from a navigation stack, this value will be updated to
* match the view's instance's current data object.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public var data:Object;
/**
* A reference to the instance that is represented by this view object.
* ViewNavigator will create and assign the instance as needed. This
* property will be nulled out when a view is destroyed.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public var instance:View;
/**
* The serialized data that the view has requested be saved to disk when
* the application is writing data to a shared object or external file.
* This object is the result of the <code>serializeData()</code> method
* on View.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public var persistenceData:Object;
/**
* The class used to create the view. ViewNavigator will expect this
* class to subclass View.
*
* @langversion 3.0
* @playerversion Flash 10
* @playerversion AIR 2.5
* @productversion Flex 4.5
*/
public var viewClass:Class;
}
}
The simple example below demonstrates how to set up a ViewNavigator inside an application and use its various features.
a href="MyView">MyView.mxml
MyView is a View that contains three buttons that each execute a different navigation operation. The Pop and Pop to First View buttons are only shown if the navigator has more than one view in its navigation stack.
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="View">
<s:layout>
<s:VerticalLayout />
</s:layout>
<s:Button label="Push" click="navigator.pushView(MyView)"/>
<s:Button label="Pop" click="navigator.popView()"
visible="{navigator.length > 1}"
includeInLayout="{navigator.length > 1}"/>
<s:Button label="Pop to First View" click="navigator.popToFirstView()"
visible="{navigator.length > 1}"
includeInLayout="{navigator.length > 1}"/>
</s:View>
a href="MyApplication">MyApplication.mxml
This is the main application file for the swf. It sets its initial view to MyView, meaning that is the view that will
be instantiated when the app starts.
<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark">
<!-- Create the ViewNavigator and have it display MyView when created -->
<s:ViewNavigator id="navigator" width="100%" height="100%" firstView="{MyView}"/>
</s:Application>
Below is an example of two views using the context property to customize a view's appearance and return object.
Favorites View
This view allows the user to define what their favorite items are. When a category in the list is selected, the view will push on a view to ask the user what their favorite thing is for that category. When this view is recreated, it will display the user's favorite item at the bottom. This component uses the context
parameter in pushView
to tell [QuestionView]
what question to ask. In addition, when instantiated, this view checks for a return object, and if there is one, displays that information at the bottom.
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
add="view1_addHandler(event)"
title="Favorites">
<s:layout>
<s:VerticalLayout gap="20"/>
</s:layout>
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
import spark.components.supportClasses.ViewReturnObject;
import spark.events.IndexChangeEvent;
protected function list1_changeHandler(event:IndexChangeEvent):void
{
navigator.pushView(QuestionView, null, list.selectedItem.token);
}
protected function view1_addHandler(event:FlexEvent):void
{
var ro:ViewReturnObject = navigator.returnedObject;
if (ro)
{
resultField.text = "Your favorite " + ro.context + " is " + ro.object;
if (ro.context == "color")
resultField.setStyle("color", ro.object);
}
else
{
resultGroup.includeInLayout = false;
resultGroup.visible = false;
}
}
]]>
</fx:Script>
<s:List id="list" width="100%" height="100%" change="list1_changeHandler(event)">
<s:dataProvider>
<s:ArrayList>
<fx:Object label="Color" token="color"/>
<fx:Object label="Food" token="food"/>
<fx:Object label="Song" token="song"/>
<fx:Object label="City" token="city"/>
<fx:Object label="Animal" token="animal"/>
<fx:Object label="Game" token="game"/>
</s:ArrayList>
</s:dataProvider>
</s:List>
<s:Group id="resultGroup" width="100%" minHeight="40">
<s:Label id="resultField" textAlign="center" width="100%" bottom="10"/>
</s:Group>
</s:View>
Question View
This view will change its prompt and title based on the context is was created in. When the view is removed, it returns the string in the text input component.
<?xml version="1.0" encoding="utf-8"?>
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark"
title="Favorite "
add="view1_addHandler(event)">
<fx:Script>
<![CDATA[
import mx.events.FlexEvent;
protected function view1_addHandler(event:FlexEvent):void
{
title += context;
labelField.text = "What if your favorite " + context + "?";
}
override public function createReturnObject():Object
{
return responseField.text;
}
]]>
</fx:Script>
<s:layout>
<s:VerticalLayout paddingLeft="10" paddingRight="10" paddingTop="10"/>
</s:layout>
<s:Label id="labelField" horizontalCenter="0" width="100%"/>
<s:TextInput id="responseField" width="100%" enter="navigator.popView()"/>
</s:View>
\
\
\
Wiki: Flex 4.5
Wiki: Mobile ActionBar
Wiki: TabbedViewNavigator and TabbedViewNavigatorApplication
Wiki: View Transitions
Wiki: ViewNavigatorApplication