20 June 2011
Basic experience with Flex and Flash Builder
Additional requirements
Beginning
In this tutorial, you use the Flash Builder 4.5.1 and Flex 4.5.1 updates to build a simple, yet fully functional employee directory application for Android devices.
You don’t need a mobile device to complete this tutorial: you can use the simple emulator available in the Flash Builder 4.5.1 update to run and debug the application.
The Employee Directory application allows you to:
In this section, you build a simple mobile application that shows a list of employees.
<?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="Home"
creationComplete="srv.send()">
<fx:Declarations>
<s:HTTPService id="srv" url="assets/employees.xml"/>
</fx:Declarations>
<s:List id="list" top="0" bottom="0" left="0" right="0"
dataProvider="{srv.lastResult.list.employee}"
labelField="lastName"/>
</s:View>
Notes:
In this section, you define a mobile item renderer for the list of employees.
<s:List id="list" top="0" bottom="0" left="0" right="0"
dataProvider="{srv.lastResult.list.employee}">
<s:itemRenderer>
<fx:Component>
<s:IconItemRenderer
label="{data.firstName} {data.lastName}"
messageField="title"/>
</fx:Component>
</s:itemRenderer>
</s:List>
In this section, you create an EmployeeDetails view that shows the details of the employee selected in the list. You learn how to navigate and pass information between views.
<?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="Employee Details">
<s:HGroup verticalAlign="middle" gap="12">
<s:Image source="assets/pics/{data.picture}"/>
<s:VGroup>
<s:Label text="{data.firstName} {data.lastName}"/>
<s:Label text="{data.title}"/>
<s:Label text="{data.department}"/>
<s:Label text="{data.city}"/>
</s:VGroup>
</s:HGroup>
</s:View>
<s:List id="list" top="0" bottom="0" left="0" right="0"
dataProvider="{srv.lastResult.list.employee}"
change="navigator.pushView(EmployeeDetails, list.selectedItem)">
<s:itemRenderer>
<fx:Component>
<s:IconItemRenderer
label="{data.firstName} {data.lastName}"
messageField="title"/>
</fx:Component>
</s:itemRenderer>
</s:List>
In this section, you provide the Employee Directory with an Action Bar:
</s:ViewNavigatorApplication> tag):<s:navigationContent>
<s:Button icon="@Embed('assets/home.png')"
click="navigator.popToFirstView()"/>
</s:navigationContent>
</fx:Declarations> tag) to create a search bar:<s:titleContent>
<s:TextInput id="key" width="100%"/>
</s:titleContent>
<s:actionContent>
<s:Button icon="@Embed('assets/search.png')" click="srv.send()"/>
</s:actionContent>
With this initial implementation, clicking the search button returns all the employees no matter what you type in the search field. You implement a working search capability in Part 6.
Note that both the EmployeeDetails and the EmployeeDirectoryHome views inherit the Home button defined in EmployeeDirectory.mxml. Although it is generally a good idea for all the views of the application to have a Home button, it is superfluous (and potentially confusing) for the Home view of the application to have a Home button (see Figure 9).
<s:titleContent> tag:<s:navigationContent/>
Note that when you open the details view for an employee, and then go back to the list using the back button of your device (or the home button of the application), the list is empty. This is because the previously active view is automatically destroyed when another view becomes active. When you click the back button, the previous view is actually re-instantiated.
Although a view is destroyed when it becomes inactive, its “data” attribute is persisted and re-assigned when the view is re-instantiated.
To persist the search results leveraging the data attribute:
<s:HTTPService id="srv" url="assets/employees.xml"
result="data=srv.lastResult.list.employee"/>
<s:List id="list" top="0" bottom="0" left="0" right="0"
dataProvider="{data}"
change="navigator.pushView(EmployeeDetails, list.selectedItem)">
<s:itemRenderer>
<fx:Component>
<s:IconItemRenderer
label="{data.firstName} {data.lastName}"
messageField="title"/>
</fx:Component>
</s:itemRenderer>
</s:List>
In this section, you allow the user to call, text, or email an employee from within the application.
<fx:Script> block just before the <s:HGoup> opening tag.<fx:Script>
<![CDATA[
]]>
</fx:Script>
<fx:Script> block, define a bindable ArrayCollection to hold the list of actions available for the selected employee:[Bindable]
protected var actions:ArrayCollection;
Note: Make sure you import the ArrayCollection class for this code to compile:
import mx.collections.ArrayCollection;
[Embed("assets/sms.png")]
private var smsIcon:Class;
[Embed("assets/phone.png")]
private var phoneIcon:Class;
[Embed("assets/mail.png")]
private var mailIcon:Class;
override public function set data(value:Object):void
{
super.data = value;
actions = new ArrayCollection();
if (data.officePhone)
{
actions.addItem({type: "tel", name: "Call office",
details: data.officePhone, icon:phoneIcon});
}
if (data.cellPhone)
{
actions.addItem({type: "tel", name: "Call mobile",
details: data.cellPhone, icon:phoneIcon});
actions.addItem({type: "sms", name: "SMS",
details: data.cellPhone, icon:smsIcon});
}
if (data.email)
{
actions.addItem({type: "mailto", name: "Email",
details: data.email, icon:mailIcon});
}
}
</s:HGroup> tag, add a List component bound to the actions list.<s:List id="list" dataProvider="{actions}"
top="160" left="0" right="0" bottom="0">
<s:itemRenderer>
<fx:Component>
<s:IconItemRenderer
paddingTop="8" paddingBottom="8" verticalGap="6"
labelField="name"
messageField="details"
decorator="{data.icon}"/>
</fx:Component>
</s:itemRenderer>
</s:List>
When you select an employee in the list, you should see the list of available actions for that employee (see Figure 11). The actions don’t work yet. You make them work in the next step.
<s:List id="list" dataProvider="{actions}"
top="160" left="0" right="0" bottom="0"
change="list_changeHandler(event)">
<s:itemRenderer>
<fx:Component>
<s:IconItemRenderer
paddingTop="8" paddingBottom="8" verticalGap="6"
labelField="name"
messageField="details"
decorator="{data.icon}"/>
</fx:Component>
</s:itemRenderer>
</s:List>
list_changeHandler as follows:protected function list_changeHandler(event:IndexChangeEvent):void
{
var action:Object = list.selectedItem;
switch (action.type)
{
case "tel":
navigateToURL(new URLRequest("tel:"+action.details));
break;
case "sms":
navigateToURL(new URLRequest("sms:"+action.details));
break;
case "mailto":
navigateToURL(new URLRequest("mailto:"+action.details));
break;
}
}
Note: Make sure you import spark.events.IndexChangeEvent (and not mx.events.IndexChangedEvent) for this code to compile:
import spark.events.IndexChangeEvent;
In this section, you change the data access logic of the application: instead of using an HTTPService, you use the SQLite database available on your device to access the data.
<dao:EmployeeDAO id="srv"/>
Note: Make sure the model namespace is bound in the View definition at the top of the mxml document:
<s:View xmlns:fx="http://ns.adobe.com/mxml/2009"
xmlns:s="library://ns.adobe.com/flex/spark" title="Home"
xmlns:dao="dao.*">
<s:Button icon="@Embed('assets/search.png')"
click="data=srv.findByName(key.text)"/>
Note that in this case, we can directly assign the return value of the findByName function to data because EmployeeDAO uses the synchronous version of the database access API.
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
In this section, you add the “View manager” and “View direct reports” actions to the Employee Details view to allow the user to navigate up and down the org chart.
<?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="Direct Reports">
<s:List id="list" top="0" bottom="0" left="0" right="0"
dataProvider="{data.directReports}"
change="navigator.pushView(EmployeeDetails, list.selectedItem)">
<s:itemRenderer>
<fx:Component>
<s:IconItemRenderer
label="{data.firstName} {data.lastName}"
messageField="title"/>
</fx:Component>
</s:itemRenderer>
</s:List>
</s:View>
if (data.manager)
{
actions.addItem({type: "employee", name: "View manager",
details: data.manager.firstName + " " + data.manager.lastName, employee: data.manager});
}
if (data.directReports && data.directReports.length > 0)
{
actions.addItem({type: "reports", name: "View direct reports",
details: "(" + data.directReports.length + ")",
employee: data});
}
case "employee":
navigator.pushView(EmployeeDetails, action.employee);
break;
case "reports":
navigator.pushView(DirectReports, action.employee);
break;
Here are some of the resources you’ll find useful during your development of applications for Android:
For more information on packaging an application for final deployment for each platform, see:
This work is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 Unported License. Permissions beyond the scope of this license, pertaining to the examples of code included within this work are available at Adobe.