Components

If you use the Flex framework, try the Tour de Flex application (see Figure 18-4). It is a good starting point for examples using components to develop AIR for Android applications. You can get it from the Android Market.

Figure 18-4. The Tour de Flex application
Figure 18-4. The Tour de Flex application

Flash Builder was initially not suited for mobile development. Components, such as the DataGrid or the Chart, were too complex and too large for the memory footprint.

Some work has been done from the ground up to optimize the framework with Flex Hero. Some components were rewritten to be mobile-optimized. The mobile theme, used when the MobileApplication tag is detected, has larger, touch-friendly controls, including for scroll bars.

The ViewNavigator helps in the development and management of screens and offers transition animations. The TabNavigator is used for subnavigation. The ActionBar is used for global navigation and messaging.

Using ActionScript and bitmaps is recommended over MXML and FXG at runtime.

If you like the convenience of components but prefer pure ActionScript development, Keith Peters has created lightweight and easy-to-use components (see http://www.min imalcomps.com/ and http://www.bit-101.com/blog/?p=2979).

 

Flash Builder ViewNavigator

Flash Builder and its Hero APIs provide functionality to handle view management.

Create a new project under File→New→Flex Mobile project. On the Mobile Settings panel, choose Application template→Mobile Application, then select Finish. Look at the main default application file. A firstView tag was added to the MobileApplica tion tag. It points to an MXML file inside a views directory:

[code]

<s:MobileApplication
xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:s=”library://ns.adboec.com/flex/spark”
firstView=”views.OpeningView”
}
}

[/code]

Notice a new directory called views inside your default application file. It contains the MXML file which was named after your project, as well as HomeView.mxml, and was given a title of HomeView. This is the default first view which appears when the application starts:

[code]

<s:View
xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:s=”library://ns.adboec.com/flex/spark”
title=”HomeView”>
<fx:Declarations> </fx:Declarations>
</s:View>

[/code]

A few new components were created especially for mobile development. The spark.components.ViewNavigatorApplication container automatically creates a ViewNavigator object. It is a container that consists of a collection of views, and is used to control the navigation between views, their addition or removal, and the navigation history.

The View is also a container. It extends from the Group component. Note its naviga tor attribute which references the ViewNavigator container and its data attribute which is used to store an Object, whether the view is currently visible or was previously visited.

The View dispatches three events of type FlexEvent. FlexEvent.VIEW_ACTIVATE and Flex Event.VIEW_DEACTIVATE are self-explanatory. FlexEvent.REMOVING is dispatched when the view is about to be deactivated.

Views are destroyed to keep a small footprint. If a particular view is complicated and may take some time to display, you can keep it in memory and set its destructionPo licy attribute to none.

Let’s add two buttons to our default view to navigate to another view:

[code]

<s:View
xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:s=”library://ns.adboec.com/flex/spark”
title=”HomeView”>
<fx:Declarations> </fx:Declarations>
<fx:Script>
private function onClick(event:MouseEvent):void {
navigator.pushView(ContextView);
}
</fx:Script>
<s:Button id=”Apples” click=”onClick(event)” y=”100″ />
<s:Button id=”Oranges” click=”onClick(event)” y=”200″ />
</s:View>

[/code]

Clicking on the buttons calls the onClick function which, in turn, calls the navigator’s pushView method. This method navigates to a view we will call ContextView. The push View method takes three arguments: the name of the view, a data object, and a transition animation of type ViewTransition. Only the first parameter is required.

Other navigation methods are popView to go back to the previous view, popToFirst View to jump to the default first view, and the self-explanatory popAll and replace View. navigator.activeView returns the current view.

Change the onClick function to pass the button ID as an argument:

[code]

private function onClick(event:MouseEvent):void {
navigator.pushView(ContextView, {fruit:event.currentTarget.id});
}

[/code]

Now create the second view to navigate to. Right-click on the views folder, create a new project under New→MXML Component, and enter ContextView in the Name field. Note that the file is based on spark.components.View.

Add one text field to populate the view with the data received and one button to navigate back to the first view. Note the add tag which is dispatched when a view is added to the container:

[code]

<s:View
xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:s=”library://ns.adboec.com/flex/spark”
title=”ContextView”>
<fx:Declarations> </fx:Declarations>
<s:add>
context.text = data.fruit;
</s:add>
<fx:Script>
private function onClick(event:MouseEvent):void {
navigator.pushView(HomeView);
}
</fx:Script>
<s:Button click=”onClick(event)” />
<s:TextArea id=”context” />
</s:View>

[/code]

Run this example and test the navigation. The context text area is populated with the data passed.

By default, a ViewTransition animates between screens, where one view slides out and the other slides in, defined as SlideViewTransition. You can change it for one of the following transitions: CrossFadeViewTransition, FlipViewTransition, or ZoomViewTran sition.

The default transition can be changed in navigator.defaultPopTransition and naviga tor.defaultPushTransition:

[code]

import spark.transitions.CrossFadeViewTransition;
import spark.transitions.FlipViewTransition;
var pushTransition = new FlipViewTransition();
navigator.defaultPushTransition = pushTransition;
var popTransition = new CrossFadeViewTransition();
navigator.defaultPopTransition = popTransition;
// OR
private function onClick(event:MouseEvent):void {
navigator.pushView(HomeView, {}, FlipViewTransition);
}

[/code]

To suppress the transition altogether, enter the following in the Default Application file:

[code]

navigator.transitionEnabled = false;
// OR
ViewNavigator.defaultPushTransition = null;
ViewNavigator.defaultPopTransition = null;

[/code]

A default ActionBar control is placed at the top of the screen. It functions as a control and navigation menu and provides contextual information, such as the current active view. It has a navigation area, a control area, and an action area. To modify it, use the navigationContent, titleContent, and actionContent tags.

By default, the name of the active view shows in the titleContent. To add a button to the navigationContent tag to go back home, use:

[code]

private function goHome():void {
navigator.popToFirstView();
}
<s:navigationContent>
<s:Button label=”Home” click=”goHome()”/>
</s:navigationContent>

[/code]

If you use it, move all navigation functionality from the views to it. Alternatively, you can choose not to use it at all. To hide it at the view level, use the following:

[code]

<s:creationComplete>
actionBarVisible = false;
</s:creationComplete>

[/code]

To hide it at the application level, use this code:

[code]

navigator.actionBar.visible = false;
navigator.actionBar.includeInLayout = false;

[/code]

Pressing the back button automatically goes back to the previous view. To overwrite this functionality, set a null navigationContent as follows:

[code]

<s:navigationContent/>

[/code]

If the user leaves the application on a specific view, you can start the application again on the same view with the same data by using the sessionCachingEnabled tag:

[code]

<s:MobileApplication
xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:s=”library://ns.adboec.com/flex/spark”
sessionCachingEnabled=”true”
firstView=”views.OpeningView”
}
}

[/code]

 

View-Based Application

The View-Based Application adds the concept of a navigator, which is a built-in navigation framework specifically built for use within mobile applications. The navigator will manage the screens within your application. Creating a new View-Based Application within Flash Builder 4.5 will result in the generation of two files. These files are the main application file, as well as the default view that will be shown within your application. Unlike the Blank Application, where the main application file was created with the <s:Application> as the parent, a View-Based Application uses the new <s:View NavigatorApplication> as its parent, as shown below:

<?xml version=”1.0″ encoding=”utf-8″?>
<s:ViewNavigatorApplication xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:s=”library://ns.adobe.com/flex/spark”
firstView=”views.ViewBasedHomeView”>
<fx:Declarations>
<!– Place non-visual elements (e.g., services, value objects) here –>
</fx:Declarations>
</s:ViewNavigatorApplication>

The second file that is created is the default view, which is automatically placed in a package named views. In this case, it was named ViewBasedHomeView, and was automatically set as the firstView property of ViewNavigatorApplication. The autogenerated code for this file is shown below:

<?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=”HomeView”>
<fx:Declarations>
<!– Place non-visual elements (e.g., services, value objects) here –>
</fx:Declarations>
</s:View>

Figure 2-3 shows the View-Based Application after adding a Label to ViewBasedHome View. As you can see, the navigation framework automatically provides a header and places the title of the current view in that header.

A View-Based Application

Now let’s explore the navigator a bit. I have created a second view for my application named SecondView. I updated ViewBasedHomeView to have a Button, and also added a Button to the SecondView shown below. As you can see, each view contains a Button with a similar clickHandler. The clickHandler simply calls the pushView function on the navigator and passes in the view that you wish to have the user navigate to. Home- View will navigate to Second View, and Second View will navigate to HomeView.

Between each view, a transition is automatically played and the title of the view is reflected in the navigation bar. This can be seen in Figures 2-4 and 2-5:

<?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=”HomeView”>
<fx:Script>
<![CDATA[
protectedfunction button1_clickHandler(event:MouseEvent):void
{
navigator.pushView(views.SecondView);
}
]]>
</fx:Script>
<fx:Declarations>
<!– Place non-visual elements (e.g., services, value objects) here –>
</fx:Declarations>
<s:Button label=”Go To Second View”
horizontalCenter=”0″ verticalCenter=”0″
click=”button1_clickHandler(event)”/>
</s:View>
<?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=”SecondView”>
<fx:Script>
<![CDATA[
protectedfunction button1_clickHandler(event:MouseEvent):void
{
navigator.pushView(views.ViewBasedHomeView);
}
]]>
</fx:Script>
<fx:Declarations>
<!– Place non-visual elements (e.g., services, value objects) here –>
</fx:Declarations>
<s:Button label=”Go To Home View”
horizontalCenter=”0″ verticalCenter=”0″
click=”button1_clickHandler(event)”/>
</s:View>

The HomeView screen

The Second View screen

The navigator has additional methods for moving between views within your application. They are as follows:

navigator.popAll()

Removes all of the views from the navigator stack. This method changes the display to a blank screen.

navigator.popToFirstView()

Removes all views except the bottom view from the navigation stack. The bottom view is the one that was first pushed onto the stack.

navigator.popView()

Pops the current view off the navigation stack. The current view is represented by the top view on the stack. The previous view on the stack becomes the current view.

navigator.pushView()

Pushes a new view onto the top of the navigation stack. The view pushed onto the stack becomes the current view.

Each of the methods described above allow for a transition to be passed in. By default, they will use a Wipe transition. All pop actions will wipe from left to right, while a push action will wipe from right to left.

Another important item to note on navigator.pushView() is the ability to pass an object into the method call. I have updated the sample below to demonstrate how to use this within your applications.

The ViewBasedHomeView shown below now includes a piece of String data (“Hello from Home View”) within the pushView() method. SecondView has also been updated to include a new Label, which is bound to the data object. This data object is what will hold the value of the object passed in through the pushView() method. Figure 2-6 shows how
SecondView is created with the Label showing our new message:

<?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=”HomeView”>
<fx:Script>
<![CDATA[
protectedfunction button1_clickHandler(event:MouseEvent):void
{
navigator.pushView(views.SecondView, “Hello from Home View”);
}
]]>
</fx:Script>
<fx:Declarations>
<!– Place non-visual elements (e.g., services, value objects) here –>
</fx:Declarations>
<s:Button label=”Go To Second View”
horizontalCenter=”0″ verticalCenter=”0″
click=”button1_clickHandler(event)”/>
</s:View>

<?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=”SecondView”>
<fx:Script>
<![CDATA[
protectedfunction button1_clickHandler(event:MouseEvent):void
{
navigator.pushView(views.ViewBasedHomeView);
}
]]>
</fx:Script>
<fx:Declarations>
<!– Place non-visual elements (e.g., services, value objects) here –>
</fx:Declarations>
<s:Label text=”{data}” horizontalCenter=”0″ top=”30″/>
<s:Button label=”Go To Home View”
horizontalCenter=”0″ verticalCenter=”0″
click=”button1_clickHandler(event)”/>
</s:View>

pushView() with data passed through

The navigation bar at the top of a View-Based Application allows you to set specific elements. These are navigationContent and actionContent. By setting these elements, your application can include a common navigation throughout. Here is an example of the View-Based Application’s main file updated with these new elements. You will notice that navigationContent, actionContent, and the Spark components are defined in MXML. Within each, I have included a Button. Each Button has a clickHandler that includes a call to one of the navigator methods. The Button labeled “Home” has a click Handler that includes a call to the popToFirstView() method, which will always send the user back to the view defined in the firstView property of the ViewNavigation Application. The Button labeled “Back” has a clickHandler that includes a call to the popView() method, which will always send the user to the previous view in the stack.

Figure 2-7 shows the application, which now includes the new navigation elements within the navigation bar:

<?xml version=”1.0″ encoding=”utf-8″?>
<s:ViewNavigatorApplication xmlns:fx=”http://ns.adobe.com/mxml/2009″
xmlns:s=”library://ns.adobe.com/flex/spark”
firstView=”views.ViewBasedHomeView”>
<fx:Script>
<![CDATA[
protectedfunction homeButton_clickHandler(event:MouseEvent):void
{
navigator.popToFirstView();
}
protectedfunction backButton_clickHandler(event:MouseEvent):void
{
navigator.popView();
}
]]>
</fx:Script>
<fx:Declarations>
<!– Place non-visual elements (e.g., services, value objects) here –>
</fx:Declarations>
<s:navigationContent>
<s:Button id=”homeButton” click=”homeButton_clickHandler(event)”
label=”Home”/>
</s:navigationContent>

<s:actionContent>
<s:Button id=”backButton” click=”backButton_clickHandler(event)”
label=”Back”/>
</s:actionContent>
</s:ViewNavigatorApplication>

 

navigationContent and actionContent

 

AIR on the Desktop Versus AIR on Android

If you want to convert an existing AIR desktop application to Android, you must make a few changes:

  • If you are using Flash Builder, the WindowedApplication application MXML tag needs to be changed to ViewNavigatorApplication. WindowedApplication assumes there is a NativeWindow, which is not the case on Android.
  • In the Application descriptor, the namespace must be 2.6 or later and the visible tag must be set to true.
  • The AIR SDK packaging command must use apk as the target.

The following desktop functionalities are not supported on Android:

ActionScript 2, ContextMenu, DatagramSocket, Dockicon, EncryptedLocalStore, HTMLoader, LocalConnection, NativeMenu, NativeWindow, PrintJob, SecureSocket, ServerSocket, StorageVolumeInfo, SystemTrayIcon, Updater, XMLSignatureValidator