How to use the Feathers
ScreenNavigator class supports navigation between screens or pages. It is best suited for working with a set of screens in a flat hierarchy.
Events dispatched from the active screen can be used to trigger navigation. Navigation can be enhanced with animation, called a transition. Feathers provides a number of transitions out of the box, and a simple API lets you create custom transitions.
First, let's create a
ScreenNavigator component and add it to the display list:
You may also set its
height, but that's optional because the
ScreenNavigator will automatically resize itself to fill the entire stage, if you don't provide explicit dimensions.
To add a new screen that the navigator can show, call
addScreen() and pass in an ID string to associate with the screen along with a
This screen's ID is
"mainMenu". We'll use this ID later when we ask the screen navigator to display this screen. There are a number of other APIs that require this ID too.
The first argument required by the
ScreenNavigatorItem constructor may be one of three types. We can pass in a
Class to instantiate, a display object that has already been instantiated, or a
Function that returns a display object. In most cases, a
Class is recommended. For more details, see the
To show a specific screen, call
showScreen(), and pass in the screen's ID. We'll use the
"mainMenu" string that we registered with
To access the currently visible screen, use the
You can also use
activeScreenID to get the ID of the active screen. In this case, again, it would be
To make the
ScreenNavigator remove the active screen, call
If the active screen dispatches an event, the
ScreenNavigator can listen for it to automatically navigate to another screen.
Before we get to that, let's make a couple of changes to our existing code. First, let's move the main menu screen's ID into a constant. Then, let's add a second screen.
The constants will help us avoid typing mistakes that the compiler can easily catch. Let's use the
MAIN_MENU constant in the call to
You probably noticed that we defined an
OPTIONS constant too. Let's add the options screen that goes with it:
Now that we have a second screen, let's look at how we can navigate from the main menu to the options screen.
Dispatch events from the screen
The best way to navigate from one screen to another is to dispatch an event from the currently active screen. Using the
ScreenNavigatorItem, we can map an event to a screen indentifier. The
ScreenNavigator will automatically navigate to a different screen when one of these events is dispatched. Let's map an event from the main menu screen that will navigate to the options screen:
setScreenIDForEvent(), we tell the
ScreenNavigatorItem that the screen navigator should navigate to the screen with the
OPTIONS ID when
MainMenuScreen.SHOW_OPTIONS is dispatched by the
MainMenuScreen, we can add a constant named
SHOW_OPTIONS that we'll use as an event type:
Then, we might dispatch this event when a button is triggered:
Next, let's repeat the process with the options screen to navigate back to the main menu screen when an event is dispatched.
OptionsScreen, we might dispatch an event when a button is triggered, similar to how we did it in
MainMenuScreen. This time, we'll just use the built in
Event.COMPLETE constant instead of defining a new one:
Now, we can navigate back and forth between the two screens.
We can call
setScreenIDForEvent() as many times as needed to listen for multiple events.
As we learned above, we can either show a screen or we can clear the currently active screen. Each of these actions can be animated, improving the user experience and adding a little bit of life to our games and apps. This animation during navigation is called a transition.
We can find a number of useful transition classes in the
feathers.motion package. One example is the
Fade class, which fades a screen by animating its
Each of the built-in transition classes has one or more static methods that you can call to create a transition function that screen navigator calls when navigating to a different screen. In this case, let's call
We can pass the result to the screen navigator's
In the code above, we didn't pass any arguments to
Fade.createFadeInTransition(). However, this function exposes some optional parameters that we can customize, if desired. For instance, we might want to customize the duration of the animation (in seconds) and the easing function:
Now, the animation will last a little longer while easing in and out.
Events when transitions start and complete
FeathersEventType.TRANSITION_START when a new screen is being shown and the transition animation begins. Similarly, it dispatches
FeathersEventType.TRANSITION_COMPLETE when the transition animation has ended.
Let's listen for
The event listener might look like this:
Optionally, we can pass properties to the screen before it is shown. If we have multiple screens that need to share some data, this is a useful way to ensure that each screen has access to it. For instance, we might have an
OptionsData class that stores things like audio volume and other common options. We'd want to pass that to the
OptionsScreen to let the user change the volume, obviously. We'd also want to pass it to other screens that play audio so that it plays at the correct volume.
In the class where we create the
ScreenNavigator, let's create an
OptionsData instance too. In a moment, we'll pass it to each screen that needs it.
Now, when we add our
OptionsScreen to the
ScreenNavigator, we pass it the
OptionsData instance in using the
properties property on the
OptionsScreen, we need to add a variable or a getter and setter named
options to match up with
We want to update the screen when the
options property changes, so we should invalidate the screen, and the
draw() function will be called again:
ScreenNavigator offers a number of advanced features to customize navigation behavior.
Call a function instead of navigating to a different screen
ScreenNavigatorItem event map can be used for more than simply navigating from one screen to another. You can also call a function when an event or signal is dispatched. Let's add a new event to the main menu that will be dispatched when an "About Our Product" button is clicked. We want it to open a website in the browser.
The function may optionally receives the event listener arguments.
Optionally, the function may receive the listener arguments for the event dispatched by the screen, if needed:
Listen to signals instead of events
Alternatively, you may use the as3-signals library instead of events to trigger navigation. Feathers doesn't actually require as3-signals as a dependency, but at runtime, Feathers will check to see if as3-signals is compiled into the SWF. If it is, then the screen navigator will enable special behavior to check if the event map is referring to an event or a signal.
If as3-signals has been detected, the
ScreenNavigator will first check a screen for a signal that's a public property before falling back to adding an event listener. For example, if the event map defines an
"complete" key, the
ScreenNavigator will check of the screen has a property named
complete. If the property exists, in must implement the
ISignal interface. If both of these conditions are true, a listener will be added to the signal. If either condition is false, then the
ScreenNavigator will fall back to adding a listener for the "complete" event instead.
Let's rework the example above to use signals instead of events. Let's start with changing how
MainMenuScreen is added to the
MainMenuScreen, we add a signal called
onOptions that will automatically be detected when the
ScreenNavigator reads the event map:
MainMenuScreen might dispatch
onOptions when a button is triggered:
OptionsScreen to use signals instead of events would be the same.