You are on page 1of 117

BlackBerry Tablet OS SDK for Adobe AIR

Version: 0.9.3 Beta


Development Guide

Published: 2011-02-17 SWD-1449712-0217110625-001

Contents
1 Overview of the BlackBerry Tablet OS SDK for Adobe AIR............................................................................... Developing Adobe AIR applications for BlackBerry Tablet OS.......................................................................... 2 Managing your application through the application life cycle......................................................................... Understanding the application life cycle.......................................................................................................... Saving the application state.............................................................................................................................. Responding to application deactivation and activation.................................................................................... Respond to deactivation and activation.................................................................................................... Responding to low memory conditions............................................................................................................ Respond to low memory conditions.......................................................................................................... Responding to low battery notifications........................................................................................................... Respond to low battery notifications........................................................................................................ 3 ActionScript components................................................................................................................................. 4 Building a UI for your application..................................................................................................................... Organizing your UI with containers.................................................................................................................. Placing a child component within a container flow................................................................................... Aligning a child component within a container flow................................................................................. Adjusting the size of a child parallel to the container flow....................................................................... Adjusting the size of a child perpendicular to the container flow............................................................. Docking a child component....................................................................................................................... Using containers to design a simple layout............................................................................................... Choosing a button for your application............................................................................................................ Create a toggle button............................................................................................................................... Create a check box..................................................................................................................................... Code sample: Creating a check box........................................................................................................... Code sample: Creating an icon button...................................................................................................... Create a label button................................................................................................................................. Formatting the text on a label button....................................................................................................... Using the Toggleswitch class..................................................................................................................... Create a segmented control...................................................................................................................... Code sample: Creating a segmented control............................................................................................. Create a radio button group...................................................................................................................... Code sample: Creating a radio button group............................................................................................ Displaying data in lists....................................................................................................................................... Create a List............................................................................................................................................... Code sample: Creating a list...................................................................................................................... 4 4 5 5 5 6 6 7 7 8 9 11 12 12 12 14 15 16 16 16 27 28 29 31 32 33 34 37 40 41 42 44 46 47 48

Adding an item to a list.............................................................................................................................. Removing an item from a list..................................................................................................................... Updating an item in a list........................................................................................................................... Create a tile list.......................................................................................................................................... Code sample: Creating a tile list................................................................................................................ Creating a section tile list.......................................................................................................................... Creating a custom list................................................................................................................................ Using the picker to implement complex lists.................................................................................................... Create and populate a DataProvider object for a picker........................................................................... Create a picker........................................................................................................................................... Update data in a picker............................................................................................................................. Code sample: Creating a picker calendar.................................................................................................. Code sample: Creating a picker clock........................................................................................................ Code sample: Creating a flip clock by using Pickerlist objects................................................................... Capturing text input.......................................................................................................................................... Create a text input field............................................................................................................................. Providing feedback and activity status to the user........................................................................................... Create a progress bar................................................................................................................................ Code sample: Creating a progress bar....................................................................................................... Create an activity indicator........................................................................................................................ Code Sample: Creating an activity indicator.............................................................................................. Code sample: Creating a percentage bar.................................................................................................. Capturing variable input with a slider............................................................................................................... Create a volume slider............................................................................................................................... Code sample: Creating a volume slider..................................................................................................... 5 Skinning your UI components........................................................................................................................... Change the default skin of a UI component..................................................................................................... Create a custom button skin class.................................................................................................................... Apply a custom button skin.............................................................................................................................. Code sample: Creating a custom button skin................................................................................................... 6 Creating dialog boxes........................................................................................................................................ Customizing buttons in a dialog box................................................................................................................. Create a dialog box........................................................................................................................................... Code sample: Creating a dialog box..................................................................................................................

49 50 50 50 52 53 59 63 64 66 69 69 71 75 78 78 79 80 81 81 83 84 85 85 87 89 89 90 92 93 96 97 97 99

7 Responding to events and gestures.................................................................................................................. 101 Respond to an event......................................................................................................................................... 101

Code sample: Detecting a swipe gesture event................................................................................................ Code sample: Detecting a multitouch gesture event....................................................................................... Code sample: Detecting a rotation gesture event............................................................................................ Code sample: Detecting an orientation change event..................................................................................... 8 Signing your application.................................................................................................................................... Configure application signing from the command line..................................................................................... Package your application from the command line........................................................................................... Sign your application from the command line..................................................................................................

103 104 105 106 108 110 110 111

9 Provide feedback.............................................................................................................................................. 112 10 Legal notice....................................................................................................................................................... 113

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Overview of the BlackBerry Tablet OS SDK for Adobe AIR

The BlackBerry Tablet OS SDK for Adobe AIR lets you to create applications for the BlackBerry PlayBook tablet, which runs the BlackBerry Tablet OS. This SDK allows you to create Adobe AIR applications that leverage the Adobe AIR 2.5 runtime environment that is built in to the BlackBerry Tablet OS. The BlackBerry Tablet OS is a multitasking operating system built upon the reliability and power of QNX Neutrino RTOS. Designed specifically to run applications developed using Adobe Flash and Adobe ActionScript, the BlackBerry Tablet OS offers developers the opportunity to create new and compelling applications and games, or to simply adapt existing ones to a tablet platform. Adobe AIR applications are built upon Flash and ActionScript technologies commonly associated with web content. However, because they run in the Adobe AIR runtime environment rather than in a plug-in to a web browser, they function as standalone applications. Additional ActionScript APIs, for use only within the Adobe AIR runtime environment, allow your application to access to a richer set of functionality than browser-based applications. For more information about Adobe AIR application development, visit http://www.adobe.com/products/air/.

Developing Adobe AIR applications for BlackBerry Tablet OS


The BlackBerry Tablet OS SDK for Adobe AIR allows you to optimize your Adobe AIR applications for the BlackBerry Tablet OS. This SDK provides APIs that extend Adobe ActionScript 3.0 and allow you to develop applications that have the look and feel of native BlackBerry PlayBook tablet applications and take advantage of some of the unique features of the OS. These APIs provide some unique UI components and predefined skins and enable you to listen for events specific to the BlackBerry Tablet OS, such as a swipe down event from the top bezel (the touch-sensitive frame around the display area of the screen). The BlackBerry Tablet OS supports the Adobe AIR 2.5 mobile device profile. The Adobe AIR 2.5 mobile profile was developed to provide the critical improvements in performance and reduction in processor usage that were necessary to bring Adobe Flash based applications to mobile devices such as smartphones and tablets. APIs have been added to ActionScript 3.0 to allow Flash applications to access some of the functionality that is unique to mobile devices, such as access to accelerometer and geolocation information and support for touch and gesture events. The BlackBerry PlayBook tablet includes the Adobe AIR 2.5 runtime environment. Applications developed for this runtime should be fully functional on the BlackBerry PlayBook tablet with no additional development required, save for adjusting the application for the unique screen size of the tablet.

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Managing your application through the application life cycle


Understanding the application life cycle

The life cycle of an application refers to the stages that an application can move through, from the time it is invoked until it is terminated. It is important to understand the implications of the various states and transitions of the life cycle on your application so that you can respond to them appropriately in your code. In its simplest form, the life cycle of your application has three stages: it starts, runs for a period of time, and then ends. While the application is running in the foreground, it is active. While your application is running and active, it can be interrupted at any time, when another application opens and replaces yours as the active application. The BlackBerry Tablet OS is a multithreaded, multitasking platform. When your application loses focus it is not terminated, but is instead deactivated and pushed to the background; the application is still running, but it is no longer the top application on the stack. A background application can reactivatedthat is, returned to the foreground at any time, or may be closed by the user, or occasionally terminated by the system, without ever becoming active again. During the application life cycle, other events might cause your application to terminate prematurely (that is, before the user has closed it). For example, when the battery drains, the tablet shuts down and closes all open applications. In addition, there are memory considerations that your application should account for. If, for example, a user has too many applications open, it could create a low memory situation. The BlackBerry Tablet OS handles low memory conditions by closing idle background applications so it can reclaim the necessary memory resources.

Saving the application state


Saving the application state ensures that when the user returns to the application, the application returns to the same condition it was in when it lost focus. A mobile application can experience a number of interruptions during its life cyclelosing application focus, low memory events, and low battery eventsthat must be managed. It is important that your application listen for these events and respond by saving the application state; any pertinent information about the current conditions of the applicationfor example, the screen element currently in focus, or any user-entered datacan be saved. When the user returns to the application, the saved state can be reloaded and the user can then continue on as before. The type of information you should save about the application state depends upon the application, and upon the likely expectations of your user. For example, for an e-reader application, the user might simply expect to return to the same page of the same book they were reading. In a text editor application or on a settings page, the user might expect that any text entered would still be available, even if those changes were not saved manually. In an interactive game, such as a driving game, you might save much more data about the state of the application. In each case, to decide what data to save and when to save it, you must first determine what data is necessary for the user to continue when the user contains state is reloaded. It is also wise to save the application state after other significant events; for example, in a game application, you might save the state each time the user completes a level.

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Responding to application deactivation and activation


The BlackBerry Tablet OS is a multitasking operating system, which means that your application can be deactivated and moved to the background at any time. Sometimes, this is user initiated, such as when the user actively leaves your application to open another application. However, a loss of focus can also be initiated by the system, or by another application. In any case, you cannot assume that the user has appropriately saved their activity in your application before it moves to the background. When your application is deactivated and pushed to the background, it is important that it first saves its state. It is also important that your application stop any unnecessary processes to preserve system resources, to avoid needlessly using system resources and risking low memory conditions. When the application is activated and returns to the foreground, it can reload the saved state, and restart any stopped processes.
NativeApplication object, which represents the application for the duration of the life cycle and which is

Each time your application transitions from the foreground to the background and back again, the

instantiated automatically when the application is invoked, dispatches one of the following events: Property
Event.DEACTIVATE Event.ACTIVATE

Description Dispatched when the application is pushed to the background. Dispatched when the application becomes the active application.

Respond to deactivation and activation


1. 2. Import therequired packages.
import fl.events.*;

Set up event listeners to listen for the Event.DEACTIVATE and Event.ACTIVATE events.
addEventListener(Event.DEACTIVATE, onDeactivate); addEventListener(Event.ACTIVATE, onActivate);

3.

Define the callback function called when the application loses focus. This function should save the state of the application and stop any unnecessary processes.
public function onDeactivate(event:Event):void { // Save state // Suspend processes }

4.

Define the callback function called when the application regains focus. This function should save the reload the state of the application and restarted any processes that were stopped.
public function onActivate(event:Event):void { // Reload state // Restart processes }

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Responding to low memory conditions


Typically, low memory conditions occur when the user has a number of applications open and running in the background, particularly if an application did not properly shut down unnecessary processes when it moved to the background. It is possible, although unlikely, for low memory conditions to occur when only the active application is open, if that application is performing some very processor-intensive functions. When the system runs low on memory, the BlackBerry Tablet OS attempts to reclaim necessary resources by closing background applications, starting with the application that has been idle the longest. The BlackBerry Tablet OS terminates the application's processes and destroys the associated NativeApplication instance, but it does not remove the application window from the list of background applications. To the user, the application appears to be running in the background. When the user returns the application to the foreground, the BlackBerry Tablet OS restarts the application and a new instance of NativeApplication is instantiated. (and destroying the associated NativeApplication instance) When the system runs low on memory, the QNXApplication class dispatches the QNXApplicationEvent.LOW_MEMORY event. You can set up an event listener in your application to listen for this event so that you can respond appropriately. When you receive a LOW_MEMORY event, your application should

immediately save state. Should the OS need to close your application to reclaim resources, no application data is lost.

If your application is terminated by the system while the application is in the background and the user attempts to reopen it, the Event.ACTIVATE event is not dispatched as it normally would be when an application in the background is activated. This is because the application is not actually moving from the background to the foreground, but is instead being restarted; the previous instance of NativeApplication was destroyed, and a new one must be created. However, because the user expects to return to the application in the state it was in when it was pushed to the background, your application should retrieve and load the saved state when it starts.
InvokeEvent.INVOKE event. This event is dispatched when an application is started and a NativeApplication

To reload the saved state after your application is restarted requires the application to listen for the

object is instantiated. Your application can listen for this event and, when it occurs, check to see whether there is an existing saved state for the application. If an existing saved state exists, your application can retrieve it and load it.

Respond to low memory conditions


1. Import the required packages.
import qnx.system; import qnx.events;

2. 3.

Set up an event listener to listen for the QNXApplicationEvent.LOW_MEMORY event.


addEventListener(QNXApplicationEvent.LOW_MEMORY, onLowMemory);

Define the callback function called when a low memory event occurs.

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function onLowMemory(event:Event):void { // Save state }

Responding to low battery notifications


If the battery of the BlackBerry PlayBook tablet drains completely, the tablet closes all applications and shuts itself down until the battery recharges. and the battery recharged. Your application can receive notifications about changes in battery level and state, so you can evaluate the remaining battery and respond appropriately, by saving the application state and warning the user, before the system shuts down. The BlackBerry Tablet OS SDK for Adobe AIR provides APIs that allow access information about battery properties and that dispatch events when the value of those properties change. The Device class provides several properties you can use to check the status of the battery: Property
Device.device.batteryMonit oringEnabled Device.device.batteryLevel

Description Turns battery monitoring on or off. When battery monitoring is turned on, this property returns a value between 0 and 100, representing the percentage of battery charge remaining. If battery monitoring is not turned on, this property returns a value of -1. When battery monitoring is turned on, this property returns the state of the battery, one of FULL, CHARGING, or UNPLUGGED. If battery monitoring is not turned on, this property returns a value of UNKNOWN.

Device.device.batteryState

The BatteryEvent class in the qnx.events package includes two events you can use to watch for changes in the status of the battery: Event
DeviceBatteryEvent.LEVEL_C HANGE DeviceBatteryEvent.STATE_C HANGE

Description Dispatched whenever a change to the battery level occurs. Dispatched whenever a change to the battery state occurs (that is, when the battery begins charging, has completed charging but is still plugged in, or is unplugged and discharging).

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

To receive information about the battery, you must set the boolean property batteryMonitoringEnabled to true. You can then add event listeners that listen for changes in the value of the battery level or state property, and you can evaluate and respond as appropriate, by saving the application state and notifying the user to charge their device when possible. Battery monitoring cannot be tested on the simulator. Because the simulator does not have a battery to monitor, the Device.device.batteryLevel and the Device.device.batteryState properties always return values of -1 and UNKNOWN, respectively.

Respond to low battery notifications


1. Import the required packages.
import qnx.system.Device; import qnx.events.DeviceBatteryEvent;

2.

Define variables for the battery level and battery state.


public static var bLevel:int; public static var bState:int;

3.

Set the deviceBatteryMonitoring property to true to access the values for the battery level and state and then initialize the values of the bLevel and bState variables.
Device.device.batteryMonitoringEnabled = true; bLevel = Device.device.batteryLevel; bState = Device.device.batteryState;

4.

Set up event listeners to listen for the DeviceBatteryEvent.LEVEL_CHANGE and DeviceBatteryEvent.STATE_CHANGE events.
addEventListener(DeviceBatteryEvent.LEVEL_CHANGE, onLevelChange); addEventListener(DeviceBatteryEvent.STATE_CHANGE, onStateChange);

5.

Define the callback methods for the event listeners. In the following code sample, the appropriate variable is updated to reflect the new level or state of the battery.
public function onLevelChange(evt:DeviceBatteryEvent):void { bLevel = evt.batteryLevel; evaluate(); } public function onStateChange(evt:DeviceBatteryEvent):void { bState = evt.batteryState; evaluate(); }

6.

Evaluate the new battery properties and respond as appropriate.


public function evaluate() { if( bState == 3 || bLevel < 10 ) { // Save state

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

displayWarning();

10

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

ActionScript components

While the BlackBerry Tablet OS SDK for Adobe AIR extends the Adobe ActionScript API in many important areas, you must use the ActionScript 3.0 APIs for data storage, networking, and device sensor functions. The following table lists some resources that you can use to learn more about ActionScript APIs. Component Data storage Description The BlackBerry Tablet OS supports the following approaches to data storage Local shared object (in the flash.net.SharedObject package) Encrypted local store (in the flash.data.EncryptedLocalStore package) File system (in the flash.filesystem package) SQLite (in the flash.data package) You can use the flash.net package to send and receive data over a network connection. You can use the flash.sensors.Accelerometer class to register an event listener for accelerometer events. The BlackBerry Tablet OS reports movement in three perpendicular planes relative to the device. You can use the flash.sensors.Geolocation class to register an event listener that processes changes in the geoposition of the device. For more information, see Detecting geolocation changes in the ActionScript 3.0 Developer's Guide.

Network communication Accelerometer

Geolocation

For more information, see the ActionScript 3.0 Reference for the Adobe Flash Platform.

11

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Building a UI for your application

The UI encompasses all visible aspects of your application, including buttons, labels, lists, dialog boxes, or any other interface component that a user uses to interact with your application. Because your application may be deployed on multiple devices, and because most devices support orientation changes, you need to pay particular attention when you design the layout of your application. Thankfully, the BlackBerry Tablet OS SDK provides classes that enable you to design and build effective layouts. In particular, the Container class provides a simple container-like mechanism for laying out an interface and for defining the alignment, flow, and spacing of UI components. The API reference provides a comprehensive set of UI components that you can use to build your application. The UI components are described in greater detail in the API reference that is included as part of this SDK. The UI components provide lightweight, customizable implementations of the classic Adobe Flash UI components that are designed from the outset to work on a mobile device. Each UI component is easily skinnable enabling you to provide a customizable look and feel for every aspect of your application.

Organizing your UI with containers


contain other containers, called subcontainers. You can use the Container class to create a container to organize the UI components of your application. The Container class handles the positioning, size, and layout of any UI component that it contains. A container can also

Containers are also useful for resizing and laying out child components to respond to orientation changes. An orientation change occurs when the user tilts the device, such as when the user switches from portrait to landscape mode. A parent container refers to any container that contains one or more subcontainers. A child container refers to any container that is nested within a parent container. To understand how child components are arranged and sized within a parent container, you must understand the following concepts: Placing a child component within a flow Aligning a child within a flow Adjusting the size of a child parallel to the container flow Adjusting the size of a child perpendicular to the container flow Docking a child component

Placing a child component within a container flow


Container flow is the layout orientation and direction of all child components relative to the near edge of the parent container. A container can define two flow directions: vertical and horizontal. In a container with a vertical flow, the near edge is the top edge of the container. In a container with a horizontal flow, the near edge is the left edge of the container.The flow position is the position of a child component within the flow of a parent container. If a parent container's flow property is set to ContainerFlow.HORIZONTAL, the container's children (which may also be containers) will appear horizontally opposed, or side by side within the container.

12

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

If a container uses a vertical flow (ContainerFlow.VERTICAL) all subcomponents within this container will appear vertically-opposed, or one on top of another.The mySub container is show below.

13

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Components appear in the order in which you add them to a container, such that the top-most component in a container is the component that is first added to the container. This is always true unless a component is docked.

Aligning a child component within a container flow


The opposite position refers to the position of a child in the direction opposite to the flow of the container.You can define the opposite position of a child by setting the align property of the parent container. The align property determines the alignment of each subcomponent in the direction opposite to the flow of the container. In a container with a vertical flow, the align property specifies the horizontal position (x coordinate) of the subcomponent, relative to the left edge of the container. In a container with a horizontal flow, the align property specifies the vertical position (y coordinate) of the subcomponent relative to the top edge of the container.

14

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The align property has the following values: ContainerAlign.NEAR ContainerAlign.MID ContainerAlign.FAR Each value represents a position relative to the initial edge of the container. You can specify the ContainerAlign.NEAR property to place a subcomponent closest to the initial edge of a parent container. You can specify the ContainerAlign.FAR property to place a subcomponent furthest from the initial edge of the parent container. The ContainerAlign.MID value is the default. The following figure illustrates each align property in a single container. You can use the container's padding property to set the amount of space (in pixels) between each subcomponent.

Adjusting the size of a child parallel to the container flow


Flow size refers to the size of a child component in the direction of the flow of the parent container. For example, the height of a button in a container with a vertical flow, or the width of a button in a container with a horizontal flow. The container sets the flow size for a child only if the child implements IContainable and the child's IContainable.size property is not 0. Otherwise, the child component's flow size is not changed during layout operations.

15

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Adjusting the size of a child perpendicular to the container flow


Opposite size refers to the size of a child in the direction opposite to the flow of the parent container. For example, the height of a button in the container with a horizontal flow, or the width of a button in a parent container with a vertical flow. The parent container will only resize a child component in the opposite direction if the child implements IContainable and IContainable.sizeMod is set to SizeMode.BOTH. When SizeMode.BOTH is set, any container alignment settings are ignored, and the opposite size for a child is set to fill the available remaining container space in the opposite direction. For an example of a component that implements opposite size, see Adjust the opposite size of UI components The following illustration shows the opposite size and flow size of subcomponents as it relates to the flow direction of a parent container.

Docking a child component


You can dock a child component to anchor it adjacent to any edge of the parent container. If a component implements IContainment, you can set its containment property to dock it to any edge of the stage. When a resize event occurs, all docked components are laid out first, in the order in which they are added to the parent. The remaining child objects are placed in the remaining container space.

Using containers to design a simple layout


You can use a simple hierarchy of parent and child containers to design an effective layout for your application. Creating an application layout that uses multiple containers and basic UI controls involves the following tasks: Create a container

16

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Create the orientation handler function Create and add subcontainers Add UI components Adjust the opposite size of UI components Use spacers to define child layout

The complete application is shown below. The sample application uses four simple containers, and some basic UI controls to define a wizard-like application layout:

Refer to Code sample: Using containers to design a simple layout for the complete sample application.

Create a container
You can create a single main container to hold all other UI components. In this task, you define the main container and add it to the stage. 1. Import the required classes.
import import import import import import import import import import flash.display.Sprite; flash.events.Event; flash.text.TextFieldAutoSize; flash.text.TextFormat; qnx.ui.buttons.LabelButton; qnx.ui.core.* qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.text.Label; qnx.ui.text.TextInput;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frrate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.

17

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

class ContainerTest extends Sprite {

4. 5.

Create the main container variable.


private var myMain:Container;

Create a constructor for your class, and invoke initializeUI().


public function ContainerTest() { initializeUI(); }

6.

Create the function initializeUI. The initializeUI function sets up the UI components that are used by the application.
private function initializeUI():void {

7.

In the initializeUI function, instantiate the main container.


myMain = new Container();

8.

In the initializeUI function, set the debug color to a hexadecimal color value. The debugColor property is useful for visualizing the bounds of each container while you develop your application. Each container can use a different color value to allow you to tweak the details of the layout.
myMain.debugColor = 0xFFCC00;

9.

A component will only overlap a margin if the container runs out of space. The margin values are specified using literals, however, it's a good idea to use variables to allow you to change a container's margins at run time. The myMain container's flow property is set to ContainerFlow.HORIZONTAL to specify that the container's children (which may also be containers) will appear horizontally-opposed, or side-by-side within the container.
myMain.margins = Vector.<Number>([20,20,20,20]); myMain.flow = ContainerFlow.HORIZONTAL;

In the initializeUI function, set the margins and the flow for the container. The margins property takes a Vector of four numbers indicating, in order, margins for the left, top, right, and bottom edges of the container.

10. In the initializeUI function, add the container to the stage.


} addChild(myMain);

18

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Create the orientation handler function


When the user re-orients the device by switching from landscape mode to portrait mode, the Event.RESIZE system event is dispatched and the stage.width and stage.height device properties are swapped. You must set up an event listener to capture the Event.RESIZE event in order to rotate and resize your application. In this task, you create an event listener and a function to handle device orientation changes. Before you begin: Create a container 1. Create the onResize function and add the call to setSize. The setSize method calls the layout function which adjusts the layout of the subcomponents according to the properties that are defined by each parent container. Call this method only after each container and each subcomponent is defined and added to the display list. Otherwise, the call will have no effect.
private function onResize(event:Event):void { trace("ContainerTest.onResize()"); myMain.setSize(stage.stageWidth, stage.stageHeight); }

2.

In the constructor for your class, create an event listener to handle stage events. In the code sample below, an event is dispatched whenever a UI component is added to the stage.
addEventListener(Event.ADDED_TO_STAGE, handleAddedToStage);

3.

Create the handleAddedToStage function. This function is called by the event listener every time an item is added to the stage. The handleAddedToStage function creates an event listener to listen for resize events that occur whenever the user changes the orientation of the device. When a resize event is detected, the onResize function is called. The handleAddedToStage function then explicitly calls the onResize function.
private function handleAddedToStage(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE,handleAddedToStage); stage.addEventListener( Event.RESIZE, onResize ); onResize(new Event(Event.RESIZE)); }

Create and add subcontainers


You can add multiple subcontainers to a parent container. Each subcontainer can use a distinct debug color. This task demonstrates how to add three subcontainers, as shown in the diagram.

19

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Before you begin: Create the orientation handler function 1. In the body of the class, add the variables for three subcontainers: mySub, mySubRight, and mySubBottom.
private var mySub:Container; private var mySubRight:Container; private var mySubBottom:Container;

2.

In the initializeUI function, create the first subcontainer: mySub. The mySub container uses a vertical flow (ContainerFlow.VERTICAL) meaning that all components within this container will appear vertically. The size and sizeUnit properties determine the size of the subcontainer. In the following code sample, size is set to 50 and sizeUnit is set to SizeUnit.PERCENT indicating that mySub will take up 50% of the main container. The default value of sizeUnit is SizeUnit.PIXELS.
mySub = new Container(); mySub.debugColor = 0xFF3300; mySub.margins = Vector.<Number>([20,40,20,40]); mySub.flow = ContainerFlow.VERTICAL; mySub.padding = 10; mySub.size = 50; mySub.sizeUnit = SizeUnit.PERCENT; mySub.align = ContainerAlign.NEAR;

3.

In the initializeUI function, create the second subcontainer: mySubRight.The mySubRight subcontainer takes up the right-side of the stage.
mySubRight = new Container(); mySubRight.margins = Vector.<Number>([10,10,10,10]); mySubRight.size = 50; mySubRight.debugColor = 0x0033FF; mySubRight.sizeUnit = SizeUnit.PERCENT; mySubRight.flow = ContainerFlow.VERTICAL; mySubRight.align = ContainerAlign.MID; mySubRight.padding = 10;

20

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

4.

In the initializeUI function, create the third subcontainer: mySubBottom. Set the containment property to Containment.DOCK_BOTTOM. Docked children are handled first in layout operations. You can dock a subcomponent to any of the four edges of a container, in the background of the stage (Containment.BACKGROUND), or you can specify that the component is not repositioned by the parent container (Containment.UNCONTAINED).
mySubBottom = new Container(); mySubBottom.margins = Vector.<Number>([5,5,5,5]); mySubBottom.debugColor = 0x33FF33; mySubBottom.size = 12; mySubBottom.sizeUnit = SizeUnit.PERCENT; mySubBottom.flow = ContainerFlow.HORIZONTAL; mySubBottom.align = ContainerAlign.FAR; mySubBottom.containment = Containment.DOCK_BOTTOM;

5.

In the initializeUI function, add the subcontainers to the main container. The mySub and mySubRight containers are added to the stage first, but not positioned. The third subcontainer, mySubBottom is added and docked to the bottom of the main container. It is positioned first leaving the remainder of the stage for the other two subcontainers.
myMain.addChild(mySub); myMain.addChild(mySubRight); myMain.addChild(mySubBottom);

Add UI controls
You can add UI controls to each of the subcontainers. Before you begin: Create and add the subcontainers. 1. In the body of the class, add the UI control variables.
private private private private var var var var firstLabel:Label; secondLabel:Label; thirdLabel:Label; fourthLabel:Label;

private var firstInput:TextInput; private var leftButton:LabelButton; private var rightButton:LabelButton;

2.

In the initializeUI function, create and add the UI components.


var labelFormat:TextFormat = new TextFormat(); labelFormat = new TextFormat(); labelFormat.size = 22; firstLabel = new Label(); firstLabel.format = labelFormat; firstLabel.text = "First label"; firstLabel.size=35; 21

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

firstLabel.sizeUnit = SizeUnit.PERCENT; firstLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(firstLabel); secondLabel = new Label(); secondLabel.format = labelFormat; secondLabel.text = "Second label"; secondLabel.size=35; secondLabel.sizeUnit = SizeUnit.PERCENT; secondLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(secondLabel); thirdLabel = new Label(); thirdLabel.format = labelFormat; thirdLabel.text = "Third label"; thirdLabel.size=35; thirdLabel.sizeUnit = SizeUnit.PERCENT; thirdLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(thirdLabel);

3.

In the initializeUI function, create and add the mySubRight subcontainer's UI components. Add a spacer to the container before the first label is added. The spacer provides padding above the label.
firstInput = new TextInput; firstInput.width = 200; fourthLabel = new Label(); fourthLabel.format = labelFormat; fourthLabel.text = "Fourth label:"; fourthLabel.width = 200; fourthLabel.size=30; fourthLabel.sizeUnit = SizeUnit.PIXELS; mySubRight.addChild(new Spacer(60)); mySubRight.addChild(fourthLabel); mySubRight.addChild(firstInput);

Adjust the opposite size of UI components


You can adjust the opposite flow size of a UI control by setting the SizeMode property. Before you begin: Add UI controls 1. In the initializeUI function, create a button. In the following code sample, the Back button specifies SizeMode.BOTH for its SizeMode property. After a layout call, the Back button will expand vertically (if the container uses a horizontal flow) to fill the space in the container.

22

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

leftButton = new LabelButton(); leftButton.label = "Back"; leftButton.size = 100; leftButton.sizeUnit = SizeUnit.PIXELS; leftButton.sizeMode = SizeMode.BOTH;

2.

Specify a size for the component (using the size property) to resize the component when a layout call occurs. In the following example, the Next button does not specify the SizeMode property. This button will not resize after a layout call.
rightButton = new LabelButton(); rightButton.label = "Next"; rightButton.size = 100;

Use spacers to define child layout


You can use spacers to position UI components in the direction of the flow of the parent container. A spacer is a simple, invisible component that adds space between components. Before you begin: Adjust the opposite size of UI components 1. In the initializeUI function, add a spacer to a container. By default, the spacer's size property is set to 100, and the SizeUnit property is set to SizeUnit.PERCENT indicating that the spacer will take up the entire container flow, until another component is added. In the following example, the spacer pushes all other components to the right-edge of the container.
mySubBottom.addChild(new Spacer());

2. 3.

Add a button to the container.


mySubBottom.addChild(leftButton);

Add another spacer to the container. The spacer, which is instantiated when it is added to the container, is set to three pixels in size.
mySubBottom.addChild(new Spacer(3,SizeUnit.PIXELS));

4.

Add another button.


mySubBottom.addChild(rightButton);

Code sample: Using containers to design a simple layout


The following code listing builds the sample container layout application below:

23

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

package { import import import import import import import import import import import import import import import import

flash.display.Sprite; flash.events.Event; flash.text.TextFieldAutoSize; flash.text.TextFormat; qnx.ui.buttons.LabelButton; qnx.ui.core.Container; qnx.ui.core.ContainerAlign; qnx.ui.core.ContainerFlow; qnx.ui.core.Containment; qnx.ui.core.SizeMode; qnx.ui.core.SizeUnit; qnx.ui.core.Spacer; qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.text.Label; qnx.ui.text.TextInput;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] // A simple container layout example public class ContainerTest extends Sprite { //containers private var myMain:Container; private var mySub:Container; private var mySubRight:Container; private var mySubBottom:Container; //the left-side of the screen labels private var firstLabel:Label; private var secondLabel:Label; private var thirdLabel:Label; private var fourthLabel:Label;

24

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

//text input for second sub container private var firstInput:TextInput; // back and next buttons private var leftButton:LabelButton; private var rightButton:LabelButton; private var myList:List; private var myDP:DataProvider; public function ContainerTest() { addEventListener(Event.ADDED_TO_STAGE,handleAddedToStage); initializeUI(); } private function handleAddedToStage(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE,handleAddedToStage); // stage is available, we can now listen for events stage.addEventListener( Event.RESIZE, onResize ); // force a resize call onResize(new Event(Event.RESIZE));

private function initializeUI():void { // create main container myMain = new Container(); myMain.margins = Vector.<Number>([20,20,20,20]); myMain.flow = ContainerFlow.HORIZONTAL; myMain.debugColor = 0xFFCC00; addChild(myMain); // create subcontainer on left side of the screen mySub = new Container(); mySub.margins = Vector.<Number>([20,40,20,40]); mySub.flow = ContainerFlow.VERTICAL; mySub.debugColor = 0xFF3300; mySub.padding = 10; mySub.size = 50; mySub.sizeUnit = SizeUnit.PERCENT; mySub.align = ContainerAlign.NEAR; // create second subcontainer on left side of the screen mySubRight = new Container(); mySubRight.margins = Vector.<Number>([10,10,10,10]); mySubRight.size = 50; mySubRight.debugColor = 0x0033FF; mySubRight.sizeUnit = SizeUnit.PERCENT; mySubRight.flow = ContainerFlow.VERTICAL; mySubRight.align = ContainerAlign.MID;

25

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

mySubRight.padding = 10; // create subcontainer as the bottom frame mySubBottom = new Container(); mySubBottom.margins = Vector.<Number>([5,5,5,5]); mySubBottom.debugColor = 0x33FF33; mySubBottom.size = 12; mySubBottom.sizeUnit = SizeUnit.PERCENT; mySubBottom.flow = ContainerFlow.HORIZONTAL; mySubBottom.align = ContainerAlign.FAR; mySubBottom.containment = Containment.DOCK_BOTTOM; // add subcontainers to main container myMain.addChild(mySub); myMain.addChild(mySubRight); myMain.addChild(mySubBottom); // create and add UI components to the left container var labelFormat:TextFormat = new TextFormat(); labelFormat.size = 22; firstLabel = new Label(); firstLabel.format = labelFormat; firstLabel.text = "First label"; firstLabel.size=35; firstLabel.sizeUnit = SizeUnit.PERCENT; firstLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(firstLabel); secondLabel = new Label(); secondLabel.format = labelFormat; secondLabel.text = "Second label"; secondLabel.size=35; secondLabel.sizeUnit = SizeUnit.PERCENT; secondLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(secondLabel); thirdLabel = new Label(); thirdLabel.format = labelFormat; thirdLabel.text = "Third label"; thirdLabel.size=35; thirdLabel.sizeUnit = SizeUnit.PERCENT; thirdLabel.autoSize = TextFieldAutoSize.LEFT; mySub.addChild(thirdLabel); // create and add UI components for right side firstInput = new TextInput; firstInput.width = 200; fourthLabel = new Label(); fourthLabel.format = labelFormat; fourthLabel.text = "Fourth label:"; fourthLabel.width = 200;

26

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

fourthLabel.size=30; fourthLabel.sizeUnit = SizeUnit.PIXELS; mySubRight.addChild(new Spacer(60)); mySubRight.addChild(fourthLabel); mySubRight.addChild(firstInput); // create and add back and next buttons leftButton = new LabelButton(); leftButton.label = "Back"; leftButton.size = 100; leftButton.sizeUnit = SizeUnit.PIXELS; leftButton.sizeMode = SizeMode.BOTH; rightButton = new LabelButton(); rightButton.label = "Next"; rightButton.size = 100; // add spacer then button then spacer then button mySubBottom.addChild(new Spacer()); mySubBottom.addChild(leftButton); mySubBottom.addChild(new Spacer(3,SizeUnit.PIXELS)); mySubBottom.addChild(rightButton);

private function onResize(event:Event):void { trace("ContainerTest.onResize()"); myMain.setSize(stage.stageWidth, stage.stageHeight); }

Choosing a button for your application


The BlackBerry Tablet OS SDK API Reference contains a variety of button implementations. Each implementation is skinnable and customizable. The BlackBerry Tablet OS SDK API provides the following button types: Class
Button

Image

Description The Button class is the most basic button type and the base class for all buttons. The BackButton class is a simple button that contains a back arrow. You can use this button to provide navigation in your application.

BackButton

27

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Class
CheckBox IconButton

Image

Description The CheckBox class is a simple check box implementation. The IconButton class is a button that contains an icon. The LabelButton class is button that contains a String. The RadioButton class is a simple radio button implementation. The radio button remains in the down state when pressed.The RadioButtonGroup is a group of related radio buttons.

LabelButton

RadioButtonGroup

SegmentedControl

ToggleSwitch

The SegmentedControl class is a group of interconnected radio buttons that force the user to select a single option from a group or related choices. The ToggleSwitch class is a simple toggle switch implementation where the switch can be dragged along a track from one state to another.

Create a toggle button


You can use the toggle property to create a simple toggle button. When the toggle property is set to true, the button maintains the down state when pressed. When the button is pressed again, the button is released and returns to the up state. 1. Import the required classes.
import flash.display.Sprite; qnx.ui.Buttons.Button;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.
28

Create an application framework by extending Sprite.

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

class MyToggle extends Sprite {

4. 5.

In the body of the class, create a variable.


var myButton:Button;

Create a constructor for your class and invoke initializeUI()


public function MyToggle() { initializeUI(); }

6.

Create a function called initializeUI to set up the toggle switch control.


private function initializeUI():void {

7.

In the initializeUI function, set the position and size of the button. The setPosition method takes the x and y position of the button, in pixels. The setSize method takes the width and height settings, in pixels.
myButton = new Button(); myButton.setPosition(200, 200); myButton.setSize(100, 50);

8. 9.

In the initializeUI function, set the toggle property to true.


myButton.toggle = true;

In the initializeUI function, add an event listener for the click event.
myButton.addEventListener(MouseEvent.CLICK, myButtonEvent);

10. In the initializeUI function, add the button to the stage.


} this.addChild(myButton);

11. Create the myButtonEvent function. In the following code sample, a trace is sent to the console indicating that the button has been pressed. The myButton.selected property is called to return the state of the button. When the button is in the down state (when it has been clicked) the selected property returns true.
function myButtonEvent(event:MouseEvent):void { trace ("myButton has been clicked, current toggle state is:" + myButton.selected); } }

Create a check box


1. Import the required classes.

29

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.CheckBox; import qnx.ui.buttons.LabelButton;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class CheckBoxSample extends Sprite {

4.

In the body of your class, create the instance variables.


private var myCheckBox:CheckBox; private var myButton:LabelButton; private var myText:TextInput;

5.

Create a constructor for your class and invoke initializeUI().


public function CheckBoxSample() { initializeUI(); }

6.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

7.

In the initializeUI function, create and position the check box. For a check box, the width property sets the width for both the check box and the text label. The width property is mandatory. You must specify a width value or the check box will not render.
myCheckBox = new CheckBox(); myCheckBox = new CheckBox(); myCheckBox.setPosition(128, 300); myCheckBox.width = 150;

8.

In the initializeUI function, set the label for the check box. The label property takes a String. The labelPadding property takes an integer to specify the number of pixels between the check box and the label.
myCheckBox.label = "Disable login"; myCheckBox.labelPadding = 5;

9.

In the initializeUI function, set the LabelPlacement property. In the code sample below, the label is placed directly above the CheckBox instance.
myCheckBox.labelPlacement = LabelPlacement.TOP;

10. In the initializeUI function, add an event listener to trap mouse click events. The event listener will call the disableButton function whenever the user clicks the check box.
30

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myCheckBox.addEventListener(MouseEvent.CLICK, disableButton);

11. In the initializeUI function, add the check box to the stage.
this.addChild(myCheckBox);

12. In the initializeUI function, create the LabelButton and add it to the stage. This label button is disabled when the user selects the check box.
myButton = new LabelButton(); myButton = new LabelButton(); myButton.setPosition(175, 300); myButton.width = 100; myButton.label = "Login"; this.addChild(myButton);

13. In the initializeUI function, create the text input field and add it to the stage.
myText = new TextInput(); myText.setPosition(175, 250); myText.width = 150; } this.addChild(myText);

14. Create the disableButton function. When the user clicks the check box, the disableButton function is called and the enabled property for the myButton and myText buttons are toggled.
function disableButton(event:MouseEvent):void { myButton.enabled = !myButton.enabled; myText.enabled = !myText.enabled; }

Code sample: Creating a check box


The following code sample uses a CheckBox object to disable a button and text input field.
package { import flash.display.Sprite; import flash.events.MouseEvent; import import import import qnx.ui.buttons.CheckBox; qnx.ui.buttons.LabelButton; qnx.ui.buttons.LabelPlacement; qnx.ui.text.TextInput;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class CheckBoxSample extends Sprite 31

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private var myCheckBox:CheckBox; private var myButton:LabelButton; private var myText:TextInput; public function CheckBoxSample() { initializeUI(); } private function initializeUI():void { myCheckBox = new CheckBox(); myCheckBox.setPosition(128, 350); myCheckBox.width = 200; myCheckBox.label = "Disable login"; myCheckBox.labelPadding = 5; myCheckBox.labelPlacement = LabelPlacement.TOP; myCheckBox.addEventListener(MouseEvent.CLICK, disableButton); this.addChild(myCheckBox); myButton = new LabelButton(); myButton.setPosition(175, 300); myButton.width = 100; myButton.label = "Login"; this.addChild(myButton); myText = new TextInput(); myText.setPosition(175, 250); myText.width = 150; this.addChild(myText);

private function disableButton(e:MouseEvent):void { myButton.enabled = !myButton.enabled; myText.enabled = !myText.enabled; } }

Code sample: Creating an icon button


The following code sample describes how to create an icon button. In the code sample below, the setIcon method is called to place an icon on a button. The image asset is located in the src/assets folder in the project.
package { import flash.display.Sprite; import qnx.ui.buttons.IconButton; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

32

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public class IconButtonTest extends Sprite { private var myIconButton:IconButton; public function IconButtonTest() { initializeUI(); } private function initializeUI():void { var myIconButton:IconButton = new IconButton(); myIconButton.setIcon("../assets/icon.gif"); myIconButton.width = 100; myIconButton.setPosition(30, 30); } this.addChild(myIconButton);

Create a label button


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.buttons.LabelButton;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class LabelButtonSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function LabelButtonSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


{ private function initializeUI():void

33

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

6.

In the initializeUI function, create and set up the button. The label property takes a String. This is the text that appears on the button. You must set the width of the button according to the length of the text, otherwise the label will overrun the bounds of the button. You can use a Format object to apply formatting to the label text. For more information about applying a format object to a label, see Format the label text for each button state.
var myButton:LabelButton; myButton = new LabelButton(); myButton.setPosition(175, 300); myButton.width = 100; myButton.label = "Login";

7.

In the initializeUI function, add the button to the stage.


} this.addChild(myButton);

Formatting the text on a label button


You can format the label text on a button by applying a TextFormat object to a button. Because a button has multiple states (one for each user-interaction), and because button states typically supply unique skins for each state, you must create and apply a TextFormat object to each button state. You can accomplish this by calling the setTextFormatForState method and specifying a TextFormat object and a button state.

Format the label text for each button state


The following task demonstrates how to create a TextFormat object for the up, down, and disabled button states and how to use the setTextFormatForState method to apply the TextFormat object to each button state. 1. Import the required classes.
import import import import import flash.display.Sprite; flash.text.TextFormat; flash.text.TextFormatAlign; qnx.ui.buttons.LabelButton; qnx.ui.skins.SkinStates;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class LabelButtonStatesSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI()

34

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function LabelButtonStatesSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create an instance of the TextFormat object for the up button state. In the following code sample, the font color is set to red. The default skin color for the up state is grey.
var format:TextFormat = new TextFormat(); format.font = "BBAlpha Sans"; format.size = 16; format.color = 0xcc0000; format.align = TextFormatAlign.CENTER;

7.

In the initializeUI function, create an instance of the TextFormat object for the down button state. In the following code sample, the font color is set to white. The default skin color for the down state is blue.
var formatDown:TextFormat = new TextFormat(); formatDown.font = "BBAlpha Sans"; formatDown.size = 16; formatDown.color = 0xFFFFFF; formatDown.align = TextFormatAlign.CENTER;

8.

In the initializeUI function, create an instance of the TextFormat object for the disabled button state. In the following code sample, the font color is set to dark grey. The default skin color for the down state is grey.
var formatDisable:TextFormat = new TextFormat(); formatDisable.font = "BBAlpha Sans"; formatDisable.size = 16; formatDisable.color = 0xCCCCCC; formatDisable.align = TextFormatAlign.CENTER;

9.

In the initializeUI function, create a LabelButton instance.


var myButton:LabelButton = new LabelButton();

10. In the initializeUI function, call the setTextFormatForState for each button state. The setTextFormatForState matches the TextFormat object with the button state. In the code sample, only the up, down, and disabled button states are assigned unique TextFormat objects. The other button states are not implemented.
myButton.setTextFormatForState(formatDisable,SkinStates.DISABLED); myButton.setTextFormatForState(format,SkinStates.UP); myButton.setTextFormatForState(formatDown,SkinStates.DOWN); myButton.setTextFormatForState(format,SkinStates.SELECTED); myButton.setTextFormatForState(format,SkinStates.DISABLED_SELECTED);

11. In the initializeUI function, add the button label and position the button on the stage.
myButton.label = "OK"; myButton.x = 175;

35

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

12. In the initializeUI function, add the button to the stage.


} this.addChild(myButton);

Code sample: Formating the label text for each button state
The following code sample describes how to apply a TextFormat object to each button state.
package { import import import import import

flash.display.Sprite; flash.text.TextFormat; flash.text.TextFormatAlign; qnx.ui.buttons.LabelButton; qnx.ui.skins.SkinStates;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class LabelButtonSample extends Sprite { public function LabelButtonStatesSample() { initializeUI(); } private function LabelButtonStatesSample():void { // create a text format for up, disabled, selected, etc. // red label text var format:TextFormat = new TextFormat(); format.font = "BBAlpha Sans"; format.size = 16; format.color = 0xcc0000; format.align = TextFormatAlign.CENTER; // create a text format for the down state // white label text var formatDown:TextFormat = new TextFormat(); formatDown.font = "BBAlpha Sans"; formatDown.size = 16; formatDown.color = 0xFFFFFF; formatDown.align = TextFormatAlign.CENTER; // create a text format for the disabled state // grey label text var formatDisable:TextFormat = new TextFormat(); formatDisable.font = "BBAlpha Sans"; formatDisable.size = 16; formatDisable.color = 0xCCCCCC; formatDisable.align = TextFormatAlign.CENTER; var myButton:LabelButton = new LabelButton();

36

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

// set the formats for each state you want to address myButton.setTextFormatForState(formatDisable,SkinStates.DISABLED); myButton.setTextFormatForState(format,SkinStates.UP); myButton.setTextFormatForState(formatDown,SkinStates.DOWN); myButton.setTextFormatForState(format,SkinStates.SELECTED); myButton.setTextFormatForState(format,SkinStates.DISABLED_SELECTED); myButton.label = "OK"; myButton.x = myButton.y = 175; } this.addChild(myButton);

Using the Toggleswitch class


The ToggleSwitch class allows you to create a simple toggle switch. The toggle switch is a sliding button that the user can drag from one state to another. Internally, it defines two states: default and selected. You can define your own states by setting the defaultLabel and selectedLabel properties. In the following illustrations, a toggle switch is defined using Light and Dark states.

Create a toggle switch


1. Import the required classes.
import flash.display.Sprite; import flash.events.Event; import import import import qnx.ui.buttons.LabelButton; qnx.ui.buttons.ToggleSwitch; qnx.ui.skins.buttons.RoundedButtonSkinBlack; qnx.ui.skins.buttons.RoundedButtonSkinWhite;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ToggleSample extends Sprite { 37

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

4.

Create the variables for the myToggle toggle switch and the myButton label button.
private var myToggle:ToggleSwitch; private var myButton:LabelButton;

5.

Create a constructor for your class and invoke initializeUI().


public function ToggleSample() { initializeUI(); }

6.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

7.

In the initializeUI function, add the LabelButton object. In the following code sample, the LabelButton class named myLabel.
var myButton:LabelButton = new LabelButton(); myButton.label = "myButton"; myButton.setPosition(200, 150); this.addChild(myButton);

8.

In the initializeUI function, create a new ToggleSwitch instance and set the position on the stage.
var myToggle:ToggleSwitch = new ToggleSwitch(); myToggle.setPosition(200, 200);

9.

In the initializeUI function, define the toggle states. You can define the toggle states by assigning a String to the defaultLabel and selectedLabel properties. In the following code sample, the Light and Dark states represent the light and dark color themes. You also set the selected property to false, indicating that the toggle will be set to the default label on initialization.
myToggle.defaultLabel = "Light"; myToggle.selectedLabel = "Dark"; myToggle.selected = false;

10. In the initializeUI function, add an event listener for the toggle switch.
myToggle.addEventListener(Event.SELECT, themeChange);

11. In the initializeUI function, add the ToggleSwitch to the stage.


} this.addChild(myToggle);

12. Add the themeChange function that is called by the event listener. The themeChange function sets the skin for the button myButton based on the current state.
function themeChange(event:Event):void { if (myToggle.selected == true) { myButton.setSkin(RoundedButtonSkinBlack); 38

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

} else { } }

myButton.setSkin(RoundedButtonSkinWhite);

Code sample: Creating a toggle switch


The following code sample uses a ToggleSwitch object to change a button theme from dark to light.
package { import flash.display.Sprite; import flash.events.Event; import import import import qnx.ui.buttons.LabelButton; qnx.ui.buttons.ToggleSwitch; qnx.ui.skins.buttons.RoundedButtonSkinBlack; qnx.ui.skins.buttons.RoundedButtonSkinWhite;

[SWF(height="600", width="1024", frameRate="30",backgroundColor="#FFFFFF")] public class ToggleSample extends Sprite { private var myToggle:ToggleSwitch; private var myButton:LabelButton; public function ToggleSample() { initializeUI(); } private function initializeUI():void { myToggle = new ToggleSwitch(); myToggle.setPosition(200, 200); myToggle.defaultLabel = "Light"; myToggle.selectedLabel = "Dark"; myToggle.selected = false; // listen the select event the toggle switch dispatches myToggle.addEventListener(Event.SELECT, themeChange); this.addChild(myToggle); myButton = new LabelButton(); myButton.label = "myButton"; myButton.setPosition(200, 150); } this.addChild(myButton); /** @private **/

39

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private function themeChange( e:Event ):void { // if the toggle is selected, set the button skin to black, else white if ( myToggle.selected == true ) { myButton.setSkin(RoundedButtonSkinBlack); } else { } }

myButton.setSkin(RoundedButtonSkinWhite);

Create a segmented control


1. Import the required classes.
import import import import flash.display.Sprite; flash.events.Event; qnx.ui.buttons.SegmentedControl; qnx.ui.data.DataProvider;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SegmentedControlExample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function SegmentedControlExample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create and populate the array. The array contains the objects that define the text that appears on each button in the segmented control. Each object must contain a label property. In the following code sample, the array contains the names of only three days. The remaining day names will be added later.

40

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var buttonArray:Array=[]; buttonArray.push({label:"Monday"}); buttonArray.push({label:"Tuesday"}); buttonArray.push({label:"Thursday"});

7.

In the initializeUI function, create and configure the segmented control.


var mySegment:SegmentedControl = new SegmentedControl(); mySegment.x = 200; mySegment.y = 200; mySegment.width = 500; mySegment.height = 50;

8.

In the initializeUI function, instantiate the DataProvider class and associate it with the segmented control that you just created.
mySegment.dataProvider = new DataProvider(buttonArray);

9.

Add an entry in the DataProvider for Wednesday. You can use the addItemAt method to add a button to the segmented control at a given index. The label property "Wednesday" is added in the second last index within the segmented control.
-1 mySegment.addItemAt({label: "Wednesday" }, mySegment.dataProvider.length

10. Add an entry in the DataProvider for Friday. You can use the addItem method to append a button to the segmented control.
mySegment.addItem({label: "Friday" });

11. In the initializeUI function, set the button that is initially selected.
mySegment.selectedIndex = 2;

12. In the initializeUI function, add the segmented control to the stage.
} this.addChild(mySegment);

Code sample: Creating a segmented control


This code sample provides an example of a SegmentedControl object that contains a button for each day of the week.
package { import flash.display.Sprite; import import import import qnx.ui.buttons.SegmentedControl; qnx.ui.data.DataProvider; qnx.ui.skins.buttons.SegmentedControlSkinBlack; qnx.ui.skins.buttons.RoundedButtonSkinBlack;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] 41

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public class SegmentedControlExample extends Sprite { public function SegmentedControlExample() { initializeUI(); } private function initializeUI():void { // create an array for the segmented control with objects //that have label properties var buttonArray:Array=[]; buttonArray.push({label:"Monday"}); buttonArray.push({label:"Tuesday"}); buttonArray.push({label:"Thursday"}); // create a segemented control var mySegment:SegmentedControl = new SegmentedControl(); mySegment.x = 200; mySegment.y = 200; mySegment.width = 500; mySegment.height = 50; // set the data provider mySegment.dataProvider = new DataProvider(buttonArray); // set the selected index to be the 3 item in the dataProvider mySegment.selectedIndex = 2; // add the control to the disply list this.addChild(mySegment); // add an item at the index mySegment.addItemAt({label: "Wednesday" }, mySegment.dataProvider.length // add an item to the end mySegment.addItem({label: "Friday" })

-1)

Create a radio button group


1. Import the required classes.
import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.RadioButton; import qnx.ui.buttons.RadioButtonGroup;

42

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class RadioButtonSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function RadioButtonSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create three radio buttons. These buttons will become the first radio button group. In the following code sample, the groupname property is set to rbg1_meals13. This is the name of the RadioButtonGroup object that will contain the radio buttons. You must specify the name of the RadioButtonGroup for each button to associate the button with a parent group. Otherwise, all radio buttons on the screen will be part of the same array. You will create the RadioButtonGroup in a later step.
var rb1:RadioButton = new RadioButton(); rb1.setPosition(100, 100) rb1.label = "Meal option 1"; rb1.groupname = "rbg1_meals13"; addChild( rb1 ); var rb2:RadioButton = new RadioButton(); rb2.setPosition(rb1.x, rb1.y + 40); rb2.label = "Meal option 2"; rb2.groupname = "rbg1_meals13"; addChild( rb2 ); var rb3:RadioButton = new RadioButton(); rb3.setPosition(rb1.x, rb2.y + 40); rb3.label = "Meal option 3"; rb3.groupname = "rbg1_meals13"; addChild( rb3 );

7.

In the initializeUI function, create the second set of radio buttons. These buttons will become the second radio button group: rbg1_meals46.
var rb4:RadioButton = new RadioButton(); rb4.setPosition(300, 100) rb4.label = "Meal option 4"; rb4.groupname = "rbg1_meals46"; addChild( rb4 ); var rb5:RadioButton = new RadioButton(); 43

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

rb5.setPosition(rb4.x, rb4.y + 40); rb5.label = "Meal option 5"; rb5.groupname = "rbg1_meals46"; addChild( rb5 ); var rb6:RadioButton = new RadioButton(); rb6.setPosition(rb4.x, rb5.y + 40); rb6.label = "Meal option 6"; rb6.groupname = "rbg1_meals46"; addChild( rb6 );

8.

In the initializeUI function, create the first radio button group, rbg1. Use the getGroup method to instantiate the radio button group by specifying a unique name for the radio button group. It's important to use a unique name for each radio button group. Call the setSelectedRadioButton method to set the initial selection. When the application loads, the radio button rb2 will be selected.
var rbg1:RadioButtonGroup; rbg1 = RadioButtonGroup.getGroup("rbg1_meals13"); rbg1.addButton(rb1); rbg1.addButton(rb2); rbg1.addButton(rb3); rbg1.addEventListener(MouseEvent.CLICK, rbg1Change); rbg1.setSelectedRadioButton(rb2);

9.

In the initializeUI function, create the second radio button group.


var rbg2:RadioButtonGroup; rbg2 = RadioButtonGroup.getGroup("rbg1_meals46"); rbg2.addButton(rb4); rbg2.addButton(rb5); rbg2.addButton(rb6); rbg2.addEventListener(MouseEvent.CLICK, rbg2Change);

10. In the initializeUI function, create the event listener functions. The functions trap mouse-click events for each radio button group.
function rbg1Change(event:MouseEvent):void { trace("rb1 change event"); } function rbg2Change(event:MouseEvent):void{ trace("rb2 change event"); }

Code sample: Creating a radio button group


package { import flash.display.Sprite; import flash.events.MouseEvent;

44

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import qnx.ui.buttons.RadioButton; import qnx.ui.buttons.RadioButtonGroup; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class RadioButtonSample extends Sprite { public function RadioButtonSample() { initializeUI(); } private function initializeUI():void { var rb1:RadioButton = new RadioButton(); rb1.setPosition(100, 100) rb1.label = "Meal option 1"; rb1.groupname = "rbg1_meals13"; addChild( rb1 ); var rb2:RadioButton = new RadioButton(); rb2.setPosition( rb1.x, rb1.y + 40 ); rb2.label = "Meal option 2"; rb2.groupname = "rbg1_meals13"; addChild( rb2 ); var rb3:RadioButton = new RadioButton(); rb3.setPosition( rb1.x, rb2.y + 40 ); rb3.label = "Meal option 3"; rb3.groupname = "rbg1_meals13"; addChild( rb3 ); var rb4:RadioButton = new RadioButton(); rb4.setPosition( 300, 100 ) rb4.label = "Meal option 4"; rb4.groupname = "rbg1_meals46"; addChild( rb4 ); var rb5:RadioButton = new RadioButton(); rb5.setPosition( rb4.x, rb4.y + 40 ); rb5.label = "Meal option 5"; rb5.groupname = "rbg1_meals46"; addChild( rb5 ); var rb6:RadioButton = new RadioButton(); rb6.setPosition( rb4.x, rb5.y + 40 ); rb6.label = "Meal option 6"; rb6.groupname = "rbg1_meals46"; addChild( rb6 ); var rbg1:RadioButtonGroup; rbg1 = RadioButtonGroup.getGroup( "rbg1_meals13" ); rbg1.addButton( rb1 ); rbg1.addButton( rb2 ); rbg1.addButton( rb3 ); rbg1.addEventListener( MouseEvent.CLICK, rbg1Change );

45

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

rbg1.setSelectedRadioButton( rb2 ); var rbg2:RadioButtonGroup; rbg2 = RadioButtonGroup.getGroup( "rbg1_meals46" ); rbg2.addButton( rb4 ); rbg2.addButton( rb5 ); rbg2.addButton( rb6 ); rbg2.addEventListener( MouseEvent.CLICK, rbg2Change ); rbg2.setSelectedRadioButton( rb5 );

private function rbg1Change( event:MouseEvent ):void { trace("rb1 change event"); } private function rbg2Change( event:MouseEvent ):void { trace("rb2 change event"); }

Displaying data in lists


The BlackBerry Tablet OS SDK contains convenient and flexible list implementations that you can use to display data and to provide the user with a selectable, scrollable list of input choices. The qnx.ui.listClasses package contains classes that you can use to create a number of different list types, with each list inheriting from the base List class. Class
List

RoundList SectionList TileList SectionTileList DropDown

Description The List class is the base list class that provides simple list functionality. You can use the ListSelectionMode class to define how the user interacts with the list, and the ScrollDirection class to define how the list scrolls. The RoundList class is a simple list class that has no scroll bar, and continues to scroll from the beginning after the final cell is reached. The SectionList class is a list implementation that contains sections, where each section contains zero or more list items. The TileList displays list items as a set of horizontally-oriented tiles, laid out in a grid format. The SectionTileList class is a variation of the SectionList that uses tiles instead of list items. The DropDown class is a simple drop-down list implementation.

46

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Create a List
1. Import the required classes.
import flash.display.Sprite; import import import import qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.listClasses.ListSelectionMode; qnx.ui.listClasses.ScrollDirection;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ListSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function ListSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create the array of objects. By default, the List object looks for the label property within the List object data. The label property contains the String that will appear inside each list cell. In the following code sample, the array is populated with an object for each month of the year, where each object contains a label property.
var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

47

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

7.

In the initializeUI function, instantiate the List class and position it on the stage. You must provide a height and width for the list, otherwise it will not render.
var myList:List = new List(); myList.setPosition(100, 200); myList.width = 300; myList.height = 100;

8.

In the initializeUI function, set the columnWidth property. Since this list will scroll horizontally, the width of each column does not need to be very many pixels in width. In a horizontally scrolling list, the columnWidth property defines the height of each cell in the list since the list is effectively oriented sideways.
myList.columnWidth = 100;

9.

In the initializeUI function, set the selectionMode property to allow multiple selections.
myList.selectionMode = ListSelectionMode.MULTIPLE;

10. In the initializeUI function, set the scrollDirection property to ScrollDirection.HORIZONTAL to allow the list to scroll horizontally.
myList.scrollDirection = ScrollDirection.HORIZONTAL;

11. In the initializeUI function, assign a DataProvider to the list. In the following code sample, a new DataProvider instance is created using the array of objects that you created in step 5.
myList.dataProvider = new DataProvider(arrMonth);

12. In the initializeUI function, add the List object to the stage.
} this.addChild(myList);

Code sample: Creating a list


package { import import import import import flash.display.Sprite; qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.listClasses.ListSelectionMode; qnx.ui.listClasses.ScrollDirection;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class ListSample extends Sprite { public function ListSample() { initializeUI(); }

48

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private function initializeUI():void { // create an array for objects var arrMonth:Array=[]; // add objects with a arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: label property "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

//create a new list var myList:List = new List(); // set the position of x and y myList.setPosition(100, 200); // set the width myList.width = 400; // set the height myList.height = 100; myList.columnWidth = 100; myList.selectionMode = ListSelectionMode.MULTIPLE; myList.scrollDirection = ScrollDirection.HORIZONTAL; myList.dataProvider = new DataProvider(arrMonth); //add the list to the display list this.addChild(myList);

Adding an item to a list


Call the addItemAt method to add an item to a list at a given index. In the following code sample, a new item is added to the list at the second index. The addItemAt method takes the object data to add and the index location to place the new data.
myList.addItemAt({label: "Q1 FY11"}, 2);

You can append a child to the list by calling the addItem method.

49

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

You can add multiple children to a given item by calling the addItemsAt method. In the following code sample, a new array of data is added at the second index. The addItemsAt method takes an array of object data and the index location to place the new data. The array data is inserted into the existing data array.
myList.addItemsAt(myNewArray, 4)

Removing an item from a list


You can remove data from a list at runtime. Call the removeItem method and specify a valid object to remove the object from a list. In the following code sample, an object with the label property "January" is removed from the list.
myList.removeItem({label: "January"});

To remove an item at a given index, use the removeItemAt method.


myList.removeItemAt(2)

To remove all items in the list, use the removeAll method.

Updating an item in a list


You can update the data in a list at runtime. To update an item with a given item use the updateItem method. In the following code sample, an object with the label property "January" is updated with a new object that contains the label property "Q1 FY11".
myList.updateItem({label: "January"}, {label: "Q1 FY11"} );

You can use the updateItemAt method to update an item at a given index.
myList.updateItemAt({label: "Q1 FY11"}, 1)

You can call the updateItemsAt method to update the data in the array starting at the fourth index, using a new array of data. The updateItemsAt method takes an array of object data and the index location at which to update the new data. The array data is inserted into the existing data array.
myList.updateItemsAt(myNewArray, 4)

Create a tile list


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.DataProvider; import qnx.ui.listClasses.TileList;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024",frameRate="30", backgroundColor="#FFFFFF")]

50

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

3.

Create an application framework by extending Sprite.


class TileListSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function TileListSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create the array. The following code sample creates an array of month names named arrMonth.
var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

7.

In the initializeUI function, create a background for the TileList instance.


var bg:Sprite = new Sprite(); bg.graphics.lineStyle(2,0xCCCCCC); bg.graphics.beginFill(0x333333,1); bg.graphics.drawRect(0,0,420,320); bg.graphics.endFill(); bg.x = 90; bg.y = 190; addChild(bg);

8.

In the initializeUI function, create the TileList instance and position it on the stage. You must set a height and width for the list. By default, each tile is 100 pixels wide.
var myTileList:TileList = new TileList(); myTileList.setPosition(100, 200); myTileList.width = 400; myTileList.height = 300;

51

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

9.

In the initializeUI function, set the number of columns and the cell padding for the TileList. The cell padding specifies the amount of pixels between each TileList cell.
myTileList.columnCount = 3; myTileList.cellPadding = 5;

10. In the initializeUI function, specify the data provider for the TileList.In the code sample below, you create a new DataProvider instance by passing in the arrMonth array that you created in step 3.
myTileList.dataProvider = new DataProvider(arrMonth);

11. In the initializeUI function, add the TileList instance to the stage.
} this.addChild(myTileList);

Code sample: Creating a tile list


The following code sample provides an example of a TileList object that contains the names of all months of the year.
{ package import flash.display.Sprite; import qnx.ui.data.DataProvider; import qnx.ui.listClasses.TileList; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class TileListSample extends Sprite { public function TileListSample() { initializeUI(); } private function initializeUI():void { var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: 52 "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"});

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

arrMonth.push({label: "December"}); var bg:Sprite = new Sprite(); bg.graphics.lineStyle(2,0xCCCCCC); bg.graphics.beginFill(0x333333,1); bg.graphics.drawRect(0,0,420,320); bg.graphics.endFill(); bg.x = 90; bg.y = 190; this.addChild(bg); var myTileList:TileList = new TileList(); myTileList.setPosition(100, 200); myTileList.width = 400; myTileList.height = 300; myTileList.columnCount = 3; myTileList.cellPadding = 5; myTileList.dataProvider = new DataProvider(arrMonth); this.addChild(myTileList);

Creating a section tile list


The SectionTileList list contains one or more sections, where each section contains one or more list items. Conceptually, and in the context of the API, a section is called an item, and each item contains children. When you add a child to a SectionList, you must first determine which item to add the child to. To accomodate both item and child data, the SectionTileList class uses the SectionDataProvider data structure to store data. The SectionDataProvider class contains the structure and functionality that is required to create and maintain a list structure with multiple sections.

Create a SectionDataProvider object


This task demonstrates how to create a SectionDataProvider object to contain month and day data for a calendar. 1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.SectionDataProvider;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SectionTileSample extends Sprite {

4.

Creat the constructor.


53

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function SectionTileSample() { }

5.

Create the createDataProvider function to create a SectionDataProvider object instance.


{ private function createDataProvider():SectionDataProvider

6.

In the createDataProvider function, create an array. In the following code sample, the arrMonth array is a simple array of objects.
var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

7. 8.

In the createDataProvider function, create a SectionDataProvider object.


var mySDP:SectionDataProvider = new SectionDataProvider();

In the createDataProvider function, populate the SectionDataProvider object. In the following code sample, a for loop is used to create an object for each month of the year. The label property of each object is set using the array of month names that you created in a previous step. Each object is added to the SectionDataProvider object by calling the addItem method. The second for loop adds 31 children to each item by calling the addChildToItem method.
for( var i:int = 0; i < arrMonth.length; i++ ) { var section:Object = new Object(); section.label = arrMonth[i].label; mySDP.addItem( section ); for( var j:int = 1; j<32; j++ ) { mySDP.addChildToItem( {label: j}, section ); } } }

54

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Create a section tile list


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.SectionDataProvider; import qnx.ui.listClasses.SectionTileList;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SectionTileSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function SectionTileSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create and populate a SectionDataProvider instance.


var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var mySDP:SectionDataProvider = new SectionDataProvider(); for( var i:int = 0; i < arrMonth.length; i++ ) { var section:Object = new Object(); section.label = arrMonth[i].label; mySDP.addItem( section ); 55

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

for( var j:int = 1; j<32; j++ ) { mySDP.addChildToItem( {label: j}, section ); }

7.

In the initializeUI function, create the SectionTileList instance and position it on the stage.
var mySectionTileList:SectionTileList = new SectionTileList(); mySectionTileList.setPosition(100, 200); mySectionTileList.width = 520; mySectionTileList.height = 300;

8.

In the initializeUI function, set the number of columns and the cell padding. In the following code sample, the section tile list contains 5 columns. The cell padding is set to 5 pixels. Each tile is 100 pixels wide by default. The width of the list is set to 520 pixels to accomodate the tiles and the padding.
mySectionTileList.columnCount = 5; mySectionTileList.cellPadding = 5;

9.

In the initializeUI function, specify the SectionDataProvider instance for the section tile list.
mySectionTileList.dataProvider = createDataProvider();

10. In the initializeUI function, add the SectionTileList instance to the stage.
} this.addChild(mySectionTileList);

Remove an item from a section tile list


The following code sample demonstrates how to create a function to remove extra day children from month items that contains less than 31 days. Before you begin: This task builds on the application that you created in the previous task. 1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.SectionDataProvider; import qnx.ui.listClasses.SectionTileList;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create the arrMonth SectionDataProvider instance, and mySectionTileList object that you created when you created and populated the list.

56

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

4.

In the SectionTileSample class, create a function called normalizeDays. In the normalizeDays function, call removeChildFromIndexAt to remove extra days from months that contain fewer than 31 days. In the following code sample, the removeChildFromIndexAt method is called to remove the 31st, 30th, and 29th days (remember that the array is zero-based) from the month object in the first index position of the array.
function normalizeDays():void{ mySectionTileList.removeChildFromIndexAt(1, 30); mySectionTileList.removeChildFromIndexAt(1, 29); mySectionTileList.removeChildFromIndexAt(1, 28); }

5.

Add the remaining code to the normalizeDays function to remove excess days from each remaining month.
mySectionTileList.removeChildFromIndexAt(3, 30); mySectionTileList.removeChildFromIndexAt(5, 30); mySectionTileList.removeChildFromIndexAt(8, 30); mySectionTileList.removeChildFromIndexAt(10, 30);

6.

In the constructor of your application, call the normalizeDays function.


normalizeDays();

Code sample: Creating a section tile list calendar


The following code sample provides an example of a calendar that was implemented using the SectionTileList class.
package { import flash.display.Sprite; import qnx.ui.data.SectionDataProvider; import qnx.ui.listClasses.SectionTileList; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class SectionTileSample extends Sprite { private var mySectionTileList:SectionTileList; public function SectionTileSample() { initializeUI(); normalizeDays(); } private function initializeUI():void { //create and setup section list 57

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

mySectionTileList = new SectionTileList(); mySectionTileList.setPosition(100, 200); mySectionTileList.width = 520; mySectionTileList.height = 300; mySectionTileList.columnCount = 5; mySectionTileList.cellPadding = 5; mySectionTileList.dataProvider = createDataProvider(); } this.addChild(mySectionTileList);

private function createDataProvider():SectionDataProvider { var arrMonth:Array=[]; arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var mySDP:SectionDataProvider = new SectionDataProvider(); for( var i:int = 0; i < arrMonth.length; i++ ) { //add month names var section:Object = new Object(); section.label = arrMonth[i].label; mySDP.addItem( section ); //add day numbers, all 31 for now for( var j:int = 1; j<32; j++ ) { mySDP.addChildToItem( {label: j}, section ); } return(mySDP); } private function normalizeDays():void { //TODO: account for leap years mySectionTileList.removeChildFromIndexAt(1, 30); mySectionTileList.removeChildFromIndexAt(1, 29); mySectionTileList.removeChildFromIndexAt(1, 28);

58

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

mySectionTileList.removeChildFromIndexAt(3, 30); mySectionTileList.removeChildFromIndexAt(5, 30); mySectionTileList.removeChildFromIndexAt(8, 30); } mySectionTileList.removeChildFromIndexAt(10, 30);

Creating a custom list


You can extend the CellRenderer or AlternatingCellRenderer classes in order to create a custom look and feel for your list. The CellRenderer class is used to draw the table cells that make up a list. The AlternatingCellRenderer class extends the CellRenderer class to provide alternating colors for the cells in a list. The following code sample demonstrates how to create a custom list class that extends the AlternatingCellRenderer class, add a check box control to each cell, add an event listener and logic to define how each cell behaves when the user clicks the check box, and create a List object that uses the setSkin method to set the new class as the skin for the list.

Create a custom cell renderer


1. Import the required classes.
import import import import flash.display.Sprite; qnx.ui.data.DataProvider; qnx.ui.listClasses.List; qnx.ui.listClasses.ListSelectionMode;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create the MyCustomCellRenderer class. In your application signature, extend the AlternatingCellRenderer class.
public class MyCustomCellRenderer extends AlternatingCellRenderer {

4.

Create the constructor.


public function MyCustomCellRenderer() { }

5.

Override the init function. The init function is called when the list is instantiated. You can add custom logic inside this function to customize each cell in the list.

59

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

override protected function init():void {

6. 7.

In the init function, call the init function of the super class (AlternatingCellRenderer).
super.init();

In the init function, create a CheckBox object. The x and y coordinates are relative to the edge of the cell. The CheckBox appears in every cell in the list.
private var myCB:CheckBox; myCB = new CheckBox(); myCB.x = 250; myCB.y = 10; this.addChild(myCB)

8.

In the init function, add an event listeners to capture mouse click events and mouse down events.
myCB.addEventListener(MouseEvent.CLICK, onClick); myCB.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown);

9.

Add the onClick function. The onClick function dispatches a new event that bubbles up whenever the check box control is selected.
private function onClick(event:MouseEvent):void { dispatchEvent( new Event( Event.SELECT, true, true ) ); }

10. Add the onMouseDown function. The onMouseDown function calls the stopImmediatePropagation method which stops the event from propagating to the parent container, or in this case, the cell. This allows the user to select the check box control without selecting the cell.
private function onMouseDown(event:MouseEvent):void { event.stopImmediatePropagation(); }

Apply a custom cell renderer to a list


Before you begin: The following code sample demonstrates how to apply a custom AlternatingCellRenderer class to a list. This code sample assumes that the MyCustomCellRenderer class exists in the same project. 1. Import the required classes.
import flash.display.Sprite; import qnx.ui.data.DataProvider; import qnx.ui.listClasses.List; import qnx.ui.listClasses.ListSelectionMode;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.

60

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


public class CustomListSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().


public function CustomListSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

Create and populate the array. The following code sample creates an array of grocery items.
var arrItems:Array=[]; arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: "Apples"}); "Potatoes"}); "Oranges"}); "Tomatoes"}); "Carrots"}); "Eggplant"}); "Celery"}); "Milk"}); "Ham"}); "Cheese"}); "Bacon"});

7.

Create and set up the List object. In the following code sample, the selectionMode property is set to ListSelectionMode.MULTIPLE to allow the user to select multiple items in the list at one time.
var myList:List = new List(); myList.setPosition(100, 200); myList.width = 300; myList.height = 300; myList.dataProvider = new DataProvider(arrItems); myList.selectionMode = ListSelectionMode.MULTIPLE;

8. 9.

Apply the AlternatingCellRenderer class to the List.


myList.setSkin(MyCustomCellRenderer);

Add the List object to the stage.


} this.addChild(myList);

61

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code sample: Creating a custom cell renderer


You can apply a custom CellRenderer to a List object by calling the setSkin method. The following code sample shows a custom cell renderer that places a check box control inside of each list cell.
package { import flash.events.Event; import flash.events.MouseEvent; import qnx.ui.buttons.CheckBox; import qnx.ui.listClasses.AlternatingCellRenderer; public class MyCustomCellRenderer extends AlternatingCellRenderer { private var myCB:CheckBox; public function MyCustomCellRenderer() { } override protected function init():void { super.init(); myCB = new CheckBox(); myCB.x = 250; myCB.y = 10; this.addChild(myCB); myCB.addEventListener( MouseEvent.CLICK, onClick ); //add this listener in order to block the mouse // down event from the list myCB.addEventListener( MouseEvent.MOUSE_DOWN, onMouseDown);

//this will prevent the cell from being selected private function onMouseDown(event:MouseEvent):void { event.stopImmediatePropagation(); } private function onClick(event:MouseEvent):void { dispatchEvent( new Event( Event.SELECT, true, true ) ); }

The following code listing creates a simple grocery list. The list calls the custom cell renderer above to place a check box on each list cell.

62

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

package { import flash.display.Sprite; import qnx.ui.data.DataProvider; import qnx.ui.listClasses.List; import qnx.ui.listClasses.ListSelectionMode; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class CustomListSample extends Sprite { public function CustomListSample() { initializeUI(); } private function initializeUI():void { var arrItems:Array=[]; arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: arrItems.push({label: "Apples"}); "Potatoes"}); "Oranges"}); "Tomatoes"}); "Carrots"}); "Eggplant"}); "Celery"}); "Milk"}); "Ham"}); "Cheese"}); "Bacon"});

var myList:List = new List(); myList.setPosition(100, 200); myList.width = 300; myList.height = 300; myList.selectionMode = ListSelectionMode.MULTIPLE; myList.dataProvider = new DataProvider(arrItems); myList.setSkin(MyCustomCellRenderer); } this.addChild(myList);

Using the picker to implement complex lists


The Picker class provides a three-columned, scrollable, selectable list that you can use to display complex data. Users can select a value from a Picker object by first clicking on the Picker to open it, then swiping up or down to scroll the PickerList to the desired value.

63

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The PickerList class implements the list items for the picker, and each PickerList instance uses a DataProvider instance to store data. Each Picker object instance contains three PickerList instances. You can use the PickerList on its own to create simple scrolling lists. Refer to Code sample: Creating a flip clock by using PickerList objects for an example of a flip clock that was built using multiple PickerList objects.

Create and populate a DataProvider object for a picker


You can create a DataProvider object that contains the day, month, and year data for the Picker object. 1. Import the required classes.
import import import import import flash.display.Sprite; flash.events.Event; qnx.ui.data.DataProvider; qnx.ui.picker.Picker; qnx.ui.text.Label;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class PickerSample extends Sprite {

4.

Create a constructor for your class and invoke createDataProvider()


public function PickerSample() { createDataProvider(); }

5.

Create the createDataProvider function to set up and initialize the UI controls.


private function createDataProvider():DataProvider {

6.
64

In the createDataProvider function. Create the array variables.

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var arrDay:Array=[]; var arrMonth:Array=[]; var arrYear:Array=[];

7.

number of days in a month is not provided.

In the createDataProvider function, populate the arrDay array with the day data and use it to create the dayDP DataProvider. This code sample assumes a simple month data model. The logic used to determine the
for (var i:int=1; i<32; i++) { arrDay.push({label: i.toString()}); } var dayDP:DataProvider=new DataProvider(arrDay);

8.

In the createDataProvider function, populate the arrMonth array with the month data and use it to create the monthDP DataProvider instance.
arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var monthDP:DataProvider=new DataProvider(arrMonth);

9.

In the createDataProvider function, populate the arrYear array with the year data and use it to create the yearDP DataProvider.
var monthDP:DataProvider=new DataProvider(arrMonth); for (var l:int=1900; l<2011; l++) { arrYear.push({label: l.toString()}); } var yearDP:DataProvider=new DataProvider(arrYear);

10. In the createDataProvider function, create the main calendar array, dpp, using the day, month, and year data that you created in the previous steps. The dpp array is an array of arrays.
var dpp:Array = new Array(); dpp.push(dayDP); dpp.push(monthDP); dpp.push(yearDP); var returnDataProvider:DataProvider = new DataProvider(dpp);

65

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

return(returnDataProvider);

Create a picker
1. Import the required classes.
import import import import import flash.display.Sprite; flash.events.Event; qnx.ui.data.DataProvider; qnx.ui.picker.Picker; qnx.ui.text.Label;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class PickerSample extends Sprite {

4.

Create a constructor for your class. Invoke createDataProvider() and initializeUI().


public function PickerSample() { createDataProvider(); initializeUI(); }

5.

Create the createDataProvider function to create and populate the DataProvider object. For more information about creating the following DataProvider instance, refer to Create and populate a DataProvider object for a picker.
private function createDataProvider():DataProvider { var arrDay:Array=[]; var arrMonth:Array=[]; var arrYear:Array=[]; for (var i:int=1; i<32; i++) { arrDay.push({label: i.toString()}); } var dayDP:DataProvider=new DataProvider(arrDay); arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"});

66

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label:

"July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var monthDP:DataProvider=new DataProvider(arrMonth); for (var l:int=1900; l<2011; l++) { arrYear.push({label: l.toString()}); } var yearDP:DataProvider=new DataProvider(arrYear); var dpp:Array = new Array(); dpp.push(dayDP); dpp.push(monthDP); dpp.push(yearDP); var returnDataProvider:DataProvider = new DataProvider(dpp); return(returnDataProvider);

6.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

7.

In the initializeUI function, create and configure the Picker object.


var calPicker:Picker = new Picker(); calPicker.width=400; calPicker.height=50; calPicker.x=calPicker.y=300;

8.

In the initializeUI function, add the DataProvider to the Picker by calling the createDataProvider function.
calPicker.dataProvider=createDataProvider(); addChild(calPicker);

9.

In the initializeUI function, set the width of each PickerList in the picker. The first argument in the setListWidth method is the index value of the PickerList instance. This array is zero-based, and the value 0 represents the first PickerList instance in the picker. The second argument represents the width of the PickerList.
calPicker.setListWidth(0,25); calPicker.setListWidth(1,50); calPicker.setListWidth(2,25);

10. In the initializeUI function, add the event listeners for the open, close, and select events.

67

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

calPicker.addEventListener(Event.OPEN,handleOpen); calPicker.addEventListener(Event.CLOSE,handleClose); calPicker.addEventListener(Event.SELECT,handleSelect);

11. In the initializeUI function, set the initial index values of the picker. The selectedIndices method takes an array of index values. In the code sample below, the values represent 1 January 2010. You can call this method at any time to set the current index of the picker. Note though that the lists will not scroll when the index value is changed. To make the lists scroll, use the PickerList's scrollToIndex method. To return the pickerlist, use the getListAt method.
} calPicker.selectedIndices=[0,0,110];

12. Create the handleSelect function, which is called when the user selects an item, and the traceItems function, that stores the selected values in variables, and outputs the items to the console. The traceItems function uses the selectedItems method to capture the currently selected item in each of the three arrays. It uses the selectedIndices method to capture the current index value, and the data property to capture the data type of the current index.
function traceItems():void { for (var j:int = 0; j <calPicker.selectedItems.length; j++) { trace("calPicker.selectedItems " +calPicker.selectedItems[j].label); selItem = calPicker.selectedItems[j].label; } trace("calPicker.selectedIndices "+calPicker.selectedIndices); selIndex = calPicker.selectedIndices; trace("calPicker.data "+calPicker.data); selObj = calPicker.data;

function handleSelect(e:Event):void { traceItems(); }

13. Create the handleOpen and handleClose functions to handle open and close events.
function handleOpen(e:Event):void { trace("Picker.open event captured"); } function handleClose(e:Event):void { trace("Picker.close event captured"); }

68

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Update data in a picker


You can create a new DataProvider instance and apply it to a Picker at run time. For example, you can create a DataProvider object that contains French month names, then use the updateItemAt method to replace the English month name array. Before you begin: Create a Picker object. 1. Create the new array and DataProvider.
var arrMonth_fr:Array = new Array(); arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: arrMonth_fr.push({label: "Janvier"}); "Fevrier"}); "Mars"}); "Avril"}); "Mai"}); "Juin"}); "Juillet"}); "Aout"}); "Septembre"}); "Octobre"}); "Novembre"}); "Decembre"});

var month_frDP:DataProvider=new DataProvider(arrMonth_fr);

2.

Call the updateItemAt method to update the second PickerList in the picker with the new array of month names.
calPicker.updateItemAt(month_frDP, 1);

Code sample: Creating a picker calendar


The following code sample demonstrates how to create a Picker that contains calendar data.
package { import flash.display.Sprite; import flash.events.Event; import qnx.ui.data.DataProvider; import qnx.ui.picker.Picker; import qnx.ui.text.Label; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#BBBBBB")] public class PickerSample extends Sprite { private var calPicker:Picker; public function PickerSample() 69

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

{ }

initializeUI();

private function initializeUI():void { calPicker = new Picker(); calPicker.width=400; calPicker.height=50; calPicker.x=calPicker.y=300; calPicker.dataProvider=createDataProvider(); addChild(calPicker); calPicker.setListWidth(0,25); calPicker.setListWidth(1,50); calPicker.setListWidth(2,25); calPicker.selectedIndices=[0,0,110]; calPicker.addEventListener(Event.OPEN,handleOpen); calPicker.addEventListener(Event.CLOSE,handleClose); calPicker.addEventListener(Event.SELECT,handleSelect); } traceItems(); function createDataProvider():DataProvider arrDay:Array=[]; arrMonth:Array=[]; arrYear:Array=[];

private { var var var

for (var i:int=1; i<32; i++) { arrDay.push({label: i.toString()}); } var dayDP:DataProvider=new DataProvider(arrDay); arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: arrMonth.push({label: "January"}); "February"}); "March"}); "April"}); "May"}); "June"}); "July"}); "August"}); "September"}); "October"}); "November"}); "December"});

var monthDP:DataProvider=new DataProvider(arrMonth); for (var l:int=1900; l<2011; l++)

70

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

{ }

arrYear.push({label: l.toString()});

var yearDP:DataProvider=new DataProvider(arrYear); var dpp:Array = new Array(); dpp.push(dayDP); dpp.push(monthDP); dpp.push(yearDP); var returnDataProvider:DataProvider = new DataProvider(dpp); return(returnDataProvider);

private function traceItems():void { for (var j:int = 0; j <calPicker.selectedItems.length; j++) { trace("Picker.selectedItems " +calPicker.selectedItems[j].label); } trace("Picker.selectedIndices "+calPicker.selectedIndices); trace("Picker.data "+calPicker.data);

private function handleSelect(e:Event):void { traceItems(); } private function handleOpen(e:Event):void { trace("Picker.open event captured"); } private function handleClose(e:Event):void { trace("Picker.close event captured"); }

Code sample: Creating a picker clock


The following code listing provides an example of a clock, implemented using the picker. The picker is updated using the system time. The user can interact with the picker by scrolling through the lists, however the picker always resets to the system time after a period of time.
package { import flash.display.Sprite; 71

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import import import import

flash.events.Event; flash.events.TimerEvent; flash.utils.Timer; flash.utils.setInterval;

import qnx.ui.data.DataProvider; import qnx.ui.picker.Picker; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class PickerClock extends Sprite { private var picker:Picker; private var timer:Timer; public function PickerClock() { initializeUI(); updatePicker(); // create a timer to run every 6 seconds timer = new Timer(6000); timer.addEventListener(TimerEvent.TIMER,handleTimerTick); timer.start(); // simple function that outputs the selected items traceItems();

private function initializeUI():void { // Create the picker and add the main DataProvider picker = new Picker(); picker.x = 300; picker.y = 175; picker.dataProvider = createDataProvider(); addChild(picker); // To customize column widths, // all widths are added up and then used for // a ratio against the component set width picker.height=50; picker.width = 200; picker.setListWidth(0,25); picker.setListWidth(1,25); picker.setListWidth(2,25); picker.addEventListener(Event.OPEN,handleOpen); picker.addEventListener(Event.CLOSE,handleClose); picker.addEventListener(Event.SELECT,handleSelect); } picker.isOpen = true;

private function handleTimerTick(e:TimerEvent):void {

72

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

updatePicker();

private function createDataProvider():DataProvider { // Create three arrays to handle hours, mins, AM PM var arrHour:Array=[]; var arrMin:Array=[]; var arrAmPm:Array=[]; //hours for (var i:int=1; i<13; i++) { arrHour.push({label: i.toString()}); } var HourDP:DataProvider=new DataProvider(arrHour); //mins arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: "00"}); "01"}); "02"}); "03"}); "04"}); "05"}); "06"}); "07"}); "08"}); "09"});

for (var k:int=10; k<60; k++) { arrMin.push({label: k.toString()}); } var MinDP:DataProvider=new DataProvider(arrMin); arrAmPm.push({label: "AM"}); arrAmPm.push({label: "PM"}); var AmPmDP:DataProvider=new DataProvider(arrAmPm); // Populate the main array var dpp:Array = new Array(); dpp.push(HourDP); dpp.push(MinDP); dpp.push(AmPmDP); var returnDataProvider:DataProvider = new DataProvider(dpp); return(returnDataProvider);

private function handleSelect(e:Event):void { traceItems(); }

73

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private function handleOpen(e:Event):void { trace("Picker.open event captured"); } private function handleClose(e:Event):void { trace("Picker.close event captured"); } private function traceItems():void { for (var j:int = 0; j <picker.selectedItems.length; j++) { trace("Picker.selectedItems " +picker.selectedItems[j].label); } trace("Picker.selectedIndices "+picker.selectedIndices); trace("Picker.data "+picker.data);

private function updatePicker():void { trace("PickerClock.updatepicker"); var mins:Number = new Date().minutes; var hours:Number = new Date().hours; var ampm:Number = 0; //add 1 if hour is 1 am if (hours == 0) { picker.selectedIndices=[11, mins, ampm]; } else if (hours == 1) { picker.selectedIndices=[0, mins, ampm]; } else if (hours > 12) { ampm = 1; hours = hours - 12; picker.selectedIndices=[hours - 1, mins, ampm]; } else { } }

picker.selectedIndices=[hours - 1, mins, ampm];

74

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code sample: Creating a flip clock by using Pickerlist objects


The following code listing provides an example of a flip clock that is implemented using Pickerlist objects that display the hour, minute, and the 12-hour period. The flip clock uses the scrollToIndex function to scroll from one cell in the list to the next, giving the clock the appearance of a flip clock. The user can interact with the clock by clicking a PickerList instance and changing the time, however the picker lists always reset to the system time after a brief period of time.
package { import import import import import import import import

flash.display.Sprite; flash.events.Event; flash.events.TimerEvent; flash.utils.Timer; qnx.ui.data.DataProvider; qnx.ui.events.ListEvent; qnx.ui.picker.PickerList; qnx.ui.progress.ActivityIndicator;

[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class PickerClock2 extends Sprite { private var pickerHour:PickerList; private var pickerMin:PickerList; private var pickerAmPm:PickerList; private var timer:Timer; public function PickerClock2() { initializeUI(); updatePicker(); // create a timer to run every 6 seconds timer = new Timer(6000); timer.addEventListener(TimerEvent.TIMER,handleTimerTick); timer.start(); } private function initializeUI():void { // arrays var arrHour:Array=[]; var arrMin:Array=[]; var arrAmPm:Array=[]; //hours for (var i:int=1; i<=12; i++) { arrHour.push({label: i.toString()}); }

75

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var hourDP:DataProvider=new DataProvider(arrHour); //mins arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: arrMin.push({label: "00"}); "01"}); "02"}); "03"}); "04"}); "05"}); "06"}); "07"}); "08"}); "09"});

for (var k:int=10; k<60; k++) { arrMin.push({label: k.toString()}); } var MinDP:DataProvider=new DataProvider(arrMin); // am pm arrAmPm.push({label: "AM"}); arrAmPm.push({label: "PM"}); var AmPmDP:DataProvider=new DataProvider(arrAmPm); // Create hours pickerlist pickerHour = new PickerList(); pickerHour.dataProvider = hourDP; pickerHour.x = 300; pickerHour.y = 175; pickerHour.height=50; pickerHour.width = 50; this.addChild(pickerHour); // Create min pickerlist pickerMin = new PickerList(); pickerMin.dataProvider = MinDP; pickerMin.x = pickerHour.x + pickerHour.width + 2; pickerMin.y = 175; pickerMin.height=50; pickerMin.width = 50; this.addChild(pickerMin); // Create am pm pickerlist pickerAmPm = new PickerList(); pickerAmPm.dataProvider = AmPmDP; pickerAmPm.x = pickerMin.x + pickerMin.width + 2; pickerAmPm.y = 175; pickerAmPm.height=50; pickerAmPm.width = 50; this.addChild(pickerAmPm);

private function updatePicker():void

76

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var mins:Date = new Date; var hours:Date = new Date();

// if it's 12 am if (hours.getHours() == 0) { pickerHour.scrollToIndex(0 + 1, 1); pickerMin.scrollToIndex(mins.getMinutes() + 2, 1); pickerAmPm.scrollToIndex(0, 1); trace ("case:1 hours: " + hours.getHours() , "mins: " + mins.getMinutes()) } // if it's 1 am else if (hours.getHours() == 1) { pickerHour.scrollToIndex(2, 1); pickerMin.scrollToIndex(mins.getMinutes() + 2, 1); pickerAmPm.scrollToIndex(0, 1); trace ("Case:2 hours: " + hours.getHours() , "mins: " + mins.getMinutes()) } // if it's after noon, set am pm to 1 else if (hours.getHours() > 12) { pickerHour.scrollToIndex(hours.getHours() - 11, 1); pickerMin.scrollToIndex(mins.getMinutes() + 2, 1); pickerAmPm.scrollToIndex(1, 1); trace ("Case:3 hours: " + hours.getHours(), "mins: " + mins.getMinutes()); } // if it's before noon else { pickerHour.scrollToIndex(hours.getHours() + 1, 1); pickerMin.scrollToIndex(mins.getMinutes() + 2, 1); pickerAmPm.scrollToIndex(0, 1); trace ("Case:4 hours: " + hours.getHours() , "mins: " + mins.getMinutes()) } } private function handleTimerTick(e:Event):void { updatePicker(); }

77

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Capturing text input


The qnx.ui.text package contains the classes required for displaying text on the screen and for gathering text input from the user. The Label class enables you to display formatted text within your application. The Label class cannot be used to gather text input, and it cannot get input focus. The TextInput class enables you to create a text input field that the user can use to enter text. When a TextInput instance gains focus, the virtual keyboard automatically appears enabling the user to enter text into the field. You can define the type of keyboard that appears, depending on the context of the current application.

Create a text input field


When the user clicks in a text input field, the virtual keyboard appears. You can define the type of keyboard for each text input field. The keyboard type defines the layout of the keyboard, including the types of keys, and the Return key type. The following task demonstrates how to create a text input field that enables the following keyboard.

1.

Import the required classes.


import import import import import flash.display.Sprite; qnx.ui.text.KeyboardType; qnx.ui.text.ReturnKeyType; qnx.ui.text.TextInput; qnx.ui.text.TextInputIconMode;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class TextInputSample extends Sprite {

4.

Create a constructor for your class and invoke initializeUI().

78

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function TextInputSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, instantiate the TextInput class and position the control on the stage.
var myInput:TextInput = new TextInput(); myInput.setPosition(200, 200); myInput.width = 300;

7.

In the initializeUI function, set the keyboard type and keyboard Enter key type. In the following code sample, the text input field is used to type a URL to connect to a remote server. The URL keyboard is specified (by specifying the KeyboardType.URL constant), and the Enter key is set to use the Connect key.
myInput.keyboardType = KeyboardType.URL; myInput.returnKeyType = ReturnKeyType.CONNECT;

8.

In the initializeUI function, set the clearIconMode property. By default, the text input field contains a clear icon that the user can click to clear the text input field. The icon is enabled by default, however you can define when the icon will be available to the user.
myInput.clearIconMode = TextInputIconMode.UNLESS_EDITING;

9.

In the initializeUI function, add the text input field to the stage.
} this.addChild(myInput);

Providing feedback and activity status to the user


You can provide temporal feedback and pending activity status indications to the user by using the ProgressBar class, PercentageBar class, and the ActivityIndicator class. The ProgressBar class is a horizontal track that takes a percentage value to represent the current progress of an ongoing operation. When you set the progress property, the track fill changes to represent the current status of the operation. The PercentageBar class contains a label that displays the current percentage value of the track. A PercentageBar object is shown in the following illustration:

79

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The ActivityIndicator class is an animation that you can enable or disable to indicate to the user that an activity is currently in progress. For example, you could create an ActivityIndicator instance to display during timeconsuming or processor-intensive operations. An ActivityIndicator instance is shown in the following illustration.

Create a progress bar


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.progress.ProgressBar;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ProgressSample extends Sprite {

4.

Create a constructor for your class and invoke initalizeUI().


public function ProgressSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create and position the ProgressBar object instance.
var myProgress:ProgressBar; myProgress = new ProgressBar(); myProgress.setPosition(400, 300); myProgress.width = 200;

7.

In the initializeUI function, add the ProgressBar instance to the stage.


this.addChild(myProgress);

80

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

8.

In the initializeUI function, set the progress value.You can use the progress property to update the fill position of the progress bar. The progress property takes a percentage value as a decimal. For example, 0.5 indicates 50% and 1 indicates 100%. You should write a function that periodically sets the progress property to reflect the current state of your operation.
} myProgress.progress = .5;

Code sample: Creating a progress bar


package { import flash.display.Sprite; import qnx.ui.buttons.IconButton; import qnx.ui.progress.PercentageBar; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class ProgressSample extends Sprite { private var myPercentage:PercentageBar; public function ProgressSample() { initializeUI(); } private function initializeUI():void { myPercentage = new PercentageBar(); myPercentage.setPosition(400, 300); myPercentage.width = 200; myPercentage.progress = .5; } this.addChild(myPercentage);

Create an activity indicator


1. Import the required classes.
import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.LabelButton; import qnx.ui.progress.ActivityIndicator;

81

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ActivityIndicatorSample extends Sprite {

4.

Create a constructor for your class, and invoke initializeUI().


public function ActivityIndicatorSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create the ActivityIndicator instance and add it to the stage.
var myActivity:ActivityIndicator = new ActivityIndicator(); myActivity.setPosition(260, 225); this.addChild(myActivity);

7.

In the initializeUI function, create a LabelButton instance and add it to the stage. In the following code sample, the LabelButton instance is used to enable and disable the activity indicator.
var myAnimate:LabelButton = new LabelButton(); myAnimate.setPosition(200, 300); myAnimate.label = "Animate"; myAnimate.width = 150; this.addChild(myAnimate);

8.

In the initializeUI function, add an event listener to capture button click events.
} myAnimate.addEventListener(MouseEvent.CLICK, onClick);

9.

Create the onClick function. The onClick function uses the isAnimating property of the ActivityIndicator to determine if the activity indicator is currently animating. If the activity indicator is currently animating, then the button label text is toggled and the animation is turned off by calling the animate method with a Boolean argument.
function onClick():void { if (!myActivity.isAnimating()) { myAnimate.label = "Stop"; myActivity.animate(true); } else {

82

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myAnimate.label = "Animate"; myActivity.animate(false);

After you finish: The ActivityIndicator object should only be visible when the application is processing. Use the isVisible property to hide the ActivityIndicator object when it is no longer needed. When you have finished with the ActivityIndicator object, use the destroy method to have the instance garbage-collected.

Code Sample: Creating an activity indicator


package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import qnx.ui.buttons.LabelButton; import qnx.ui.progress.ActivityIndicator; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class ActivityIndicatorSample extends Sprite { private var myActivity:ActivityIndicator; private var myAnimate:LabelButton; public function ActivityIndicatorSample() { initializeUI(); } private function initializeUI():void { myActivity = new ActivityIndicator(); myActivity.setPosition(260, 225); this.addChild(myActivity); myAnimate= new LabelButton(); myAnimate.setPosition(200, 300); myAnimate.label = "Animate"; myAnimate.width = 150; this.addChild(myAnimate); } myAnimate.addEventListener(MouseEvent.CLICK, onClick);

private function onClick(e:MouseEvent):void { if (!myActivity.isAnimating()) { myAnimate.label = "Stop";

83

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myActivity.animate(true) } else { myAnimate.label = "Animate"; myActivity.animate(false); }

Code sample: Creating a percentage bar


package { import flash.display.Sprite; import flash.events.TimerEvent; import flash.utils.Timer; import qnx.ui.progress.PercentageBar; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class myPercentageSample extends Sprite { private var myPercentage:PercentageBar; private var timer:Timer; private var counter:int; public function myPercentageSample() { initializeUI(); } private function initializeUI():void { myPercentage = new PercentageBar(); myPercentage.setPosition(400, 300); myPercentage.width = 200; myPercentage.progress = 0; this.addChild(myPercentage); // counter to keep track of how many times the timer has ticked counter = 0; timer = new Timer(100,100); timer.addEventListener(TimerEvent.TIMER,handleTimerTick); timer.addEventListener(TimerEvent.TIMER_COMPLETE,handleTimerComplete); timer.start(); } private function handleTimerComplete(e:TimerEvent):void { timer.removeEventListener(TimerEvent.TIMER,handleTimerTick); timer.removeEventListener(TimerEvent.TIMER_COMPLETE,handleTimerComplete); counter = 0; 84

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

} private function handleTimerTick(e:TimerEvent):void { counter++; myPercentage.progress = counter/100; }

Capturing variable input with a slider


The Slider class enables the user to input variable data by dragging a thumb across a track. The VolumeSlider class is used to adjust volume levels for media playback. A volume slider control is shown in the illustration below:

Create a volume slider


1. Import the required classes.
import flash.display.Sprite; import qnx.ui.slider.VolumeSlider; import qnx.ui.events.SliderEvent;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30",backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SliderSample extends Sprite {

4. 5.

Create the VolumeSlider variable.


private var myVSlider:VolumeSlider;

Create a constructor for your class and invoke initializeUI().


public function SliderSample() { initializeUI(); }

6.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

7.

In the initializeUI function, create the VolumeSlider object and position it on the stage.
85

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var myVSlider:VolumeSlider = new VolumeSlider(); myVSlider.setPosition(300, 300);

8.

In the initializeUI function, set the minimum and maximum value of the slider control. The minimum property defines the value at the left edge of the slider track, while the maximum property defines the value at the right edge of the slider track.
myVSlider.minimum = 0; myVSlider.maximum = 100;

9.

In the initializeUI function, set the fill gradient for the slider. The fillColors property takes an array of two color codes that are used to create a gradient. The first value in the array defines the right edge of the gradient. The second value in the array defines the left edge of the gradient.
myVSlider.fillColors = [0xFF0033,0xFF6699];

10. In the initializeUI function, set the initial value of the slider control.
myVSlider.value = 50;

11. In the initializeUI function, add the event listeners. The event listeners use event types that are defined in the SliderEvent class to capture slider movement, slider start, and slider stop events.
myVSlider.addEventListener( SliderEvent.MOVE, sliderChange ); myVSlider.addEventListener( SliderEvent.START, sliderStart ); myVSlider.addEventListener( SliderEvent.END, sliderStop );

12. In the initializeUI function, add the VolumeSlider object to the stage.
} this.addChild( myVSlider );

13. Create the event functions. The functions in the following code sample are used to output the current slider value and thumb state to the console. The values change as the user drags the slider. The thumb skin icon changes as the user drags the thumb from the left edge of the track to the right edge of the track.
function sliderChange( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "slider value: ", newlevel ); } function sliderStart( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "started moving at: ", newlevel ); } function sliderStop( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "stopped moving at: ", newlevel ); }

86

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code sample: Creating a volume slider


package { import flash.display.Sprite; import qnx.ui.events.SliderEvent; import qnx.ui.slider.VolumeSlider; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class SliderSample extends Sprite { /** @private **/ private var myVSlider:VolumeSlider; public function SliderSample() { initializeUI(); } private function initializeUI():void { myVSlider = new VolumeSlider(); myVSlider.setPosition(300, 300); myVSlider.minimum = 0; myVSlider.maximum = 100; myVSlider.value = 50; // listen to the when the slider moves myVSlider.addEventListener( SliderEvent.MOVE, sliderChange ); myVSlider.addEventListener( SliderEvent.START, sliderStart ); // listen to the end of the slider event myVSlider.addEventListener( SliderEvent.END, sliderStop ); this.addChild( myVSlider );

private function sliderChange( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "slider value: ", newlevel ); } private function sliderStart( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "started moving at: ", newlevel ); } private function sliderStop( event:SliderEvent ) : void { var newlevel:int = Math.round( event.target.value ); trace( "stopped moving at: ", newlevel ); 87

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

88

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Skinning your UI components

The BlackBerry Tablet OS supports custom skinning, allowing you to provide a custom look and feel for the UI components in your application. By default, the SDK provides the light color scheme and the dark color scheme. Each scheme includes a set of custom skins, one for each skinnable UI component in the API. The light color scheme is enabled by default. A skin can be any type of DisplayObject instance and is typically made up of multiple graphic assets. You can apply an asset to a component to reflect a state change. For example, a button skin may contain multiple graphic assets, where each asset reflects a button state (down, up, disabled). These component states are defined in qnx.ui.skins.SkinStates. Some components are more complex than others and require more complex skins. For example, a button has only a single skin for each state, while a segmented control has two skins: a background skin and a button skin. You can create your own custom skin by extending the qnx.ui.skins.UISkin class. The qnx.ui.skins.UISkin class is the base class for all UI component skins.

Change the default skin of a UI component


You can change the color scheme of a segmented control from light (default) to dark by changing the component's skin. 1. Import the required classes.
import flash.display.Sprite; import import import import qnx.ui.buttons.SegmentedControl; qnx.ui.data.DataProvider; qnx.ui.skins.buttons.SegmentedControlSkinBlack; qnx.ui.skins.buttons.RoundedButtonSkinBlack;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class SkinSample extends Sprite {

4.

Create a constructor for the class and invoke initializeUI().


public function SkinSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.

89

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private function initializeUI():void {

6.

In the initializeUI function, create a SegmentedControl object instance.


var buttonArray:Array=[]; buttonArray.push({label:"Monday"}); buttonArray.push({label:"Tuesday"}); buttonArray.push({label:"Wednesday"}); buttonArray.push({label:"Thursday"}); buttonArray.push({label:"Friday"}); var mySegment:SegmentedControl = new SegmentedControl(); mySegment.x = 200; mySegment.y = 200; mySegment.width = 500; mySegment.height = 50; mySegment.dataProvider = new DataProvider(buttonArray); mySegment.selectedIndex = 2; this.addChild(mySegment);

7.

In the initializeUI function, call the setBackgroundSkin method, passing in the SegmentedControlSkinBlack skin asset class. This changes the background skin of the SegmentedControl instance to the dark color scheme asset.
mySegment.setBackgroundSkin(SegmentedControlSkinBlack);

8.

In the initializeUI function, call the setButtonSkin method, passing in the RoundedButtonSkinBlack skin asset class. This changes the skin of each button in the SegmentedControl instance to use the asset from the dark color scheme.
} mySegment.setButtonSkin(RoundedButtonSkinBlack);

After you finish: For more information about the light and dark color scheme assets, see the SkinAssets class in the qnx.ui.skins package.

Create a custom button skin class


In the following task you create a custom button skin and apply it to a set of buttons. 1. Import the required classes.
import qnx.ui.skins.SkinAssets; import qnx.ui.skins.UISkin; import qnx.ui.skins.SkinStates;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

90

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

3.

In your class signature, extend the UISkin class. The UISkin class implements the qnx.ui.skins.ISkin interface and provides the base functionality required for loading and registering your skin assets.
public class CustomButtonSkin extends UISkin {

4.

Create the constructor.


public function CustomButtonSkin() { super(); }

5.

Override the initializeStates method.The initializeStates function is used to register your skin assets to associate them with UI component states.
override protected function initializeStates():void {

6.

Create variables for the skin assets. In the following code sample, you create skin assets for the up, down, selected, and disabled skin states.
protected protected protected protected var var var var upSkin:Sprite; selectedSkin:Sprite; disabledSkin:Sprite; downSkin:Sprite;

7.

In the initializeStates function, create the skin assets. Each skin is instantiated as a Sprite object. Each skin is filled using a different hexadecimal color code to create a unique look for each button state. The drawRoundRect method is used and each button skin will have a rounded edge.
upSkin = new Sprite(); upSkin.graphics.beginFill(0xFF6600); upSkin.graphics.drawRoundRect(0,0,50,50, 10,10); upSkin.graphics.endFill(); downSkin = new Sprite(); downSkin.graphics.beginFill(0x333333); downSkin.graphics.drawRoundRect(0,0,50,50, 10,10); downSkin.graphics.endFill(); disabledSkin = new Sprite(); disabledSkin.graphics.beginFill(0xCC0000); disabledSkin.graphics.drawRoundRect(0,0,50,50, 10,10); disabledSkin.graphics.endFill(); selectedSkin = new Sprite(); selectedSkin.graphics.beginFill(0x000000); selectedSkin.graphics.drawRoundRect(0,0,50,50, 10,10); selectedSkin.graphics.endFill();

8.

In the initializeStates function, register your skin assets by calling the setSkinState method for each skin asset. The setSkinState method takes a skin state constant and a skin asset. It associates the skin asset with the UI component state, such that when a button is pressed, or a list is rendered, the appropriate skin asset is displayed. In the code sample below, each skin asset is associated with the proper state.
91

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

setSkinState(SkinStates.UP, upSkin); setSkinState(SkinStates.SELECTED,selectedSkin); setSkinState(SkinStates.DISABLED, disabledSkin); setSkinState(SkinStates.DOWN, downSkin);

9.

In the initializeStates function, set the default skin state by calling the showSkin method.
} showSkin(upSkin);

Apply a custom button skin


Before you begin: Create a custom button skin. This example assumes that you created the custom button skin class CustomButtonSkin in the same project as the following sample application. Otherwise, you'd need to import the class into your sample application. 1. Import the required classes.
import qnx.ui.buttons.Button; import qnx.ui.buttons.LabelButton;

2.

Add the following statement to your class, directly before the class signature. This statement sets the stage width and height, the frame rate, and the background color of your application.
[SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")]

3.

Create an application framework by extending Sprite.


class ButtonSample extends Sprite {

4.

Create a constructor for the class and invoke initializeUI().


public function ButtonSample() { initializeUI(); }

5.

Create the initializeUI function to set up and initialize the UI controls.


private function initializeUI():void {

6.

In the initializeUI function, create a toggle button that calls the setSkin method.In the following code sample, the setSkin method takes the name of the custom skin class.
var myToggleButton:Button; myToggleButton = new Button(); myToggleButton.setPosition(200, 200); myToggleButton.setSize(100, 50);

92

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myToggleButton.toggle = true; myToggleButton.setSkin(CustomButtonSkin); addChild(myToggleButton);

7.

In the initializeUI function, create a label button that calls the setSkin method.
var myLabelButton:LabelButton; myLabelButton = new LabelButton(); myLabelButton.setPosition(200, 300); myLabelButton.setSize(150, 50); myLabelButton.label = "My Label Button"; myLabelButton.setSkin(CustomButtonSkin); } addChild(myLabelButton);

8.

Build and run the application. The buttons are rounded and the colours appears as you defined them the custom skin class. When you click the buttons, notice that each button state is also skinned.

Code sample: Creating a custom button skin


This code sample contains a small sample application that uses a custom button skin class. When you build and run this sample application, you must make sure that both the ButtonSample class and the CustomButtonSkin class are located in the same source project. Otherwise, you must import the CustomButtonSkin class into your sample application. The sample application ButtonSample creates two buttons and adds them to the stage. Each button calls the setSkin method to set the custom skin CustomButtonSkin class as the button skin.
package { import flash.display.Sprite; import flash.events.MouseEvent; import qnx.ui.buttons.Button; import qnx.ui.buttons.LabelButton; [SWF(height="600", width="1024", frameRate="30", backgroundColor="#FFFFFF")] public class ButtonSample extends Sprite { private var myToggleButton:Button; private var myLabelButton:LabelButton; public function ButtonSample() { initializeUI(); } private function initializeUI():void

93

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

{ myToggleButton = new Button(); myToggleButton.setPosition(200, 200); myToggleButton.setSize(100, 50); myToggleButton.toggle = true; myToggleButton.setSkin(CustomButtonSkin); addChild(myToggleButton); myLabelButton = new LabelButton(); myLabelButton.setPosition(200, 300); myLabelButton.setSize(150, 50); myLabelButton.label = "My Label Button"; myLabelButton.setSkin(CustomButtonSkin); addChild(myLabelButton); } }

The CustomButtonSkin class is listed below.


package { import flash.display.Sprite; import flash.geom.Rectangle; import qnx.ui.skins.SkinAssets; import qnx.ui.skins.SkinStates; import qnx.ui.skins.UISkin; public class CustomButtonSkin extends UISkin { /** @private **/ protected var upSkin:Sprite; /** @private **/ protected var selectedSkin:Sprite; /** @private **/ protected var disabledSkin:Sprite; /** @private **/ protected var downSkin:Sprite; /** @private **/ protected var gridRect:Rectangle; public function CustomButtonSkin() { super(); } override protected function initializeStates():void { gridRect = new Rectangle(8,8,30,30); 94

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

upSkin = new Sprite(); upSkin.graphics.beginFill(0xFF6600); upSkin.graphics.drawRoundRect(0,0,50,50, 10,10); upSkin.graphics.endFill(); upSkin.scale9Grid = gridRect; downSkin = new Sprite(); downSkin.graphics.beginFill(0x333333); downSkin.graphics.drawRoundRect(0,0,50,50, 10,10); downSkin.graphics.endFill(); downSkin.scale9Grid = gridRect; disabledSkin = new Sprite(); disabledSkin.graphics.beginFill(0xCC0000); disabledSkin.graphics.drawRoundRect(0,0,50,50, 10,10); disabledSkin.graphics.endFill(); disabledSkin.scale9Grid = gridRect; selectedSkin = new Sprite(); selectedSkin.graphics.beginFill(0x000000); selectedSkin.graphics.drawRoundRect(0,0,50,50, 10,10); selectedSkin.graphics.endFill(); selectedSkin.scale9Grid = gridRect; setSkinState(SkinStates.UP, upSkin); setSkinState(SkinStates.SELECTED,selectedSkin); setSkinState(SkinStates.DISABLED, disabledSkin); setSkinState(SkinStates.DOWN, downSkin); showSkin(upSkin); } }

95

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Creating dialog boxes

Your application can prompt users when your application state changes. For example, if a user is one of the top scoring players in a game application, you can prompt them to add their name to the leaderboard. You can use one of the pre-defined dialog boxes in the qnx.dialog package to communicate with your user. To optimize visibility for a dialog box in the context of your application, you can control the size, position, and alignnment of a dialog box on the screen. You can set the values for size, position, and alignment by using the contstant values provided in the other classes in the qnx.dialog package. Dialog box
AlertDialog LoginDialog PasswordChangeDialog PopupList PromptDialog

Description This dialog box presents a message and a series of buttons. This dialog box presents two text input boxes, a check box, and a series of buttons. This dialog box presents three text input boxes and a series of buttons. This dialog box presents a list of and a series of buttons. This dialog box presents a text input box and a series of buttons.

Before you display your dialog box, you should choose the modality of your dialog box. Modality
System Modal

Description A system modal dialog box locks the UI until the user dismisses the dialog box. Until the user dimisses the dialog box, the user cannot use any system gestures to exit the application or return to the main menu while a system modal dialog box is displayed. You should avoid using system modal dialog boxes if possible. To open a system modal dialog box, you must invoke Dialog.show() with no parameters. Application modal dialog boxes lock the application process. The user cannot interact with the application while the dialog box is displayed. However, the user can minimize or close the application. To open an application modal dialog box, invoke Dialog.show() and pass the application's window group as a parameter:
myDialog.show(IowWindow.getAirWindow().group)

Application Modal

For more information about setting properties of the dialog box, see the API Reference for the BlackBerry Tablet OS SDK for Adobe AIR.

96

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Customizing buttons in a dialog box


The appearance of a dialog box is controlled by the BlackBerry Tablet OS. However, you can customize the appearance and behaviour of buttons in a dialog box by invoking Dialog.setButtonPropertyAt() specifying the following parameters: Parameter Property name Value Value Provide one of the constants found in the DialogButtonProperty class. Provide an object that is appropriate to the type of property you want to apply. For example, if you specify the ENABLED property in the first parameter, you must pass a boolean value in this parameter. Similarly, if you specify the SKIN property, you must pass an object that implements the ISkin interface. Provide the index of the button to which you want to apply the property that you specified in the first parameter. The Adobe AIR runtime assigns an index of 0 to your first button.

Index

Create a dialog box


1. Import the required classes and interfaces.
import import import import import import flash.display.Sprite; flash.events.Event; flash.events.MouseEvent; qnx.dialog.*; qnx.ui.buttons.LabelButton; qnx.ui.text.*;

2.

Add the following statement to your class before the class declaration. This statement sets the width, height, frame rate, and background color of the Stage.
[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")]

3.

Create an application framework by extending the Sprite class.


public class DialogDemo extends Sprite { public function DialogDemo() { } }

4.

Create an instance variable that refers to a Label object. This label reports which button on the dialog the user presses. Add this statement to your application framework, before your constructor.
private var lblWhichButton:Label = new Label();

5.

Create the initializeUI() method to setup and initialize the UI components.

97

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

private function initializeUI():void { }

6.

In initializeUI(), add a button to invoke your dialog box, and center the button on the screen.
var btnShowDialog:LabelButton = new LabelButton(); btnShowDialog.label = "Click here"; btnShowDialog.x = (stage.stageWidth - btnShowDialog.width)/2; btnShowDialog.y = (stage.stageHeight - btnShowDialog.height)/2;

7.

Add an event listener to your button to capture click events. Invoke the ButtonClicked() method when the BlackBerry Tablet OS SDK reports a click event.
btnShowDialog.addEventListener(MouseEvent.CLICK, buttonClicked);

8.

In initializeUI(), configure the label object you created in step 4. Center the label on the Stage below the button.
lblWhichButton.x = (stage.stageWidth - btnShowDialog.width)/2; lblWhichButton.y = btnShowDialog.y + btnShowDialog.height; lblWhichButton.width = 600; lblWhichButton.text = "";

9.

In initializeUI(), add the button and label to the Stage.


addChild(btnShowDialog); addChild(lblWhichButton);

10. In the constructor for your class, invoke initializeUI().


initializeUI();

11. Create the ButtonClicked() method to respond to click events on your button.
public function ButtonClicked(event:Object):void { }

12. In ButtonClicked(), create an AlertDialog object.


var myDialog:AlertDialog = new AlertDialog(); myDialog.title = "Dialog"; myDialog.message = "This is a small alert dialog"; myDialog.addButton("OK"); myDialog.addButton("Cancel"); myDialog.dialogSize = DialogSize.SIZE_SMALL;

13. Add an event listener to the button in the dialog box to capture click events. Invoke the alertButtonClicked() method when the BlackBerry Tablet OS SDK reports a click event.
myDialog.addEventListener(Event.SELECT, alertButtonClicked);

14. Display the dialog box for the user.


myDialog.show();

15. Create the alertButtonClicked() method to respond to click events in the dialog.
98

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function alertButtonClicked(event:Object):void { }

16. In alertButtonClicked(), update the value of the label on the Stage when the user clicks on a button in the dialog.
lblWhichButton.text = "Index of button Clicked: " + e.target.selectedIndex;

After you finish: For a complete code sample, see "Code sample: Create a dialog box".

Code sample: Creating a dialog box


package { import flash.display.Sprite; import flash.events.Event; import flash.events.MouseEvent; import qnx.dialog.*; import qnx.display.IowWindow; import qnx.ui.buttons.LabelButton; import qnx.ui.text.*; [SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class Dialogs extends Sprite { private var lblWhichButton:Label = new Label(); public function Dialogs() { var btnShowDialog:LabelButton = new LabelButton(); btnShowDialog.label = "Click here"; btnShowDialog.x = (stage.stageWidth - btnShowDialog.width)/2; btnShowDialog.y = (stage.stageHeight - btnShowDialog.height)/2; btnShowDialog.addEventListener(MouseEvent.CLICK, ButtonClicked); lblWhichButton.x = (stage.stageWidth - btnShowDialog.width)/2; lblWhichButton.y = btnShowDialog.y + btnShowDialog.height; lblWhichButton.width = 600; lblWhichButton.text = "Button index reported here."; addChild(btnShowDialog); addChild(lblWhichButton);

public function ButtonClicked(event:Object):void { var myDialog:AlertDialog = new AlertDialog(); myDialog.dialogSize = DialogSize.SIZE_SMALL; myDialog.addEventListener(Event.SELECT, alertButtonClicked); 99

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

myDialog.title = "Dialog"; myDialog.message = "This is a small alert dialog"; myDialog.addButton("OK"); myDialog.addButton("Cancel"); myDialog.show(IowWindow.getAirWindow().group);

public function alertButtonClicked(event:Object):void { lblWhichButton.text = "Button Clicked Index: " + event.target.selectedIndex; }

100

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Responding to events and gestures

The most common events are those generated by a user. When a user touches the screen or tilts the BlackBerry PlayBook tablet, BlackBerry Tablet OS sends your application a notification of the event. Other events are generated by the BlackBerry Tablet OS. For example, if the battery power level is low, the BlackBerry Tablet OS attempts to notify all applications. The BlackBerry Tablet OS passes event information to your application by using the Adobe Flash event model. In the Flash event model, the BlackBerry Tablet OS attempts to notify an object about an event. If the event is not processed, the BlackBerry Tablet OS notifies the next object in the object hierarchy until the event is processed. You can add an event handler to any object by invoking addEventListener(). For example, when you create a button you can add an event handler:
myButton.addEventListener(event, method)

When the event specified by the event parameter occurs, the BlackBerry Tablet OS invokes the method specified by the method parameter Most applications should listen for low battery power level, low available memory, and foreground status events. For more information about those events, see Managing your application through the application life cycle. The following table describes some of the API packages related to events. For more information, see the API reference for BlackBerry Tablet OS or the Adobe ActionScript 3.0 Reference for the Adobe Flash Platform. API package
qnx.events

qnx.ui.events flash.events

Description This package contains event classes that you can use to capture BlackBerry Tablet OS specific events (for example, low battery power level, and requests to release the media service connection). This package contains event classes that you can use to capture events related to BlackBerry Tablet OS UI components. This package contains event classes that you can use to capture events that are generated by the Adobe AIR runtime, events related to application state (foreground, background), geolocation, and the accelerometer. You can use this package to detect the following gestures: Pan Rotate Swipe Zoom

Respond to an event
The following steps demonstrate how to respond to a swipe gesture. 1. Import the required classes and interfaces.

101

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

import import import import

flash.display.Sprite; flash.events.TransformGestureEvent; flash.ui.Multitouch; flash.ui.MultitouchInputMode;

import qnx.ui.text.Label;

2.

Add the following statement to your class before the class declaration. This statement sets the width, height, frame rate, and background color of the Stage.
[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")]

3.

Create an application framework by extending the Sprite class.


public class SwipeDemo extends Sprite { public function SwipeDemo() { } }

4.

Create an instance variable that refers to a Label object. This label reports the direction that the user swipes. Add this statement to your application framework, before your constructor.
private var _lblStatus:Label = new Label();

5.

Create the initializeUI() method to setup and initialize the UI components.


private function initializeUI():void { }

6.

In initializeUI(), configure the label object you created in step 5.Center the label on the screen and add it to the Stage.
lblStatus.y = (stage.stageHeight - lblStatus.height)/2; lblStatus.x = (stage.stageWidth - lblStatus.width)/2; lblStatus.width = stage.stageWidth; lblStatus.text = "Drag your finger across the screen"; addChild(lblStatus);

7. 8.

In initializeUI(), set the input mode to GESTURE.


Multitouch.inputMode = MultitouchInputMode.GESTURE;

In initializeUI(), add an event listener for swipe gestures. Invoke the onSwipe() method when the BlackBerry Tablet OS SDK reports a swipe gesture.
stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, onSwipe);

9.

In the constructor for your class, invoke initializeUI().


initializeUI();

10. Create the onSwipe() method to process the event.

102

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

public function onSwipe(event:TransformGestureEvent):void { }

11. In onSwipe(), create a String variable to hold the interpretation of the swipe event.
var strSwipe:String = "";

12. In onSwipe(), test the event's offsetX property to determine if the user swiped left.
if ( event.offsetX == -1 ) strSwipe = "Swipe direction: Left";

13. Create tests to detect swipes in other directions.


if ( event.offsetX == 1 ) strSwipe = "Swipe direction: Right"; if ( event.offsetY == -1 ) strSwipe = "Swipe direction: Up"; if ( event.offsetY == 1 ) strSwipe = "Swipe direction: Down";

14. Set the text property of the Label on the Stage to display the interpretation of the swipe event.
lblStatus.text = strSwipe;

After you finish: For a complete code sample, see "Code Sample: Detect a swipe gesture".

Code sample: Detecting a swipe gesture event


package { import import import import flash.display.Sprite; flash.events.TransformGestureEvent; flash.ui.Multitouch; flash.ui.MultitouchInputMode;

import qnx.ui.text.Label; [SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class SwipeDemo extends Sprite { private var lblStatus:Label = new Label(); public function SwipeDemo() { lblStatus.y = (stage.stageHeight - lblStatus.height)/2; lblStatus.x = (stage.stageWidth - lblStatus.width)/2; lblStatus.width = stage.stageWidth; lblStatus.text = "Drag your finger across the screen"; addChild(lblStatus); Multitouch.inputMode = MultitouchInputMode.GESTURE; stage.addEventListener(TransformGestureEvent.GESTURE_SWIPE, onSwipe); } public function onSwipe(event:TransformGestureEvent):void 103

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

var strSwipe:String = ""; if if if if ( ( ( ( event.offsetX event.offsetX event.offsetY event.offsetY == == == == -1 ) strSwipe = "Swipe direction: Left"; 1 ) strSwipe = "Swipe direction: Right"; -1 ) strSwipe = "Swipe direction: Up"; 1 ) strSwipe = "Swipe direction: Down";

lblStatus.text = strSwipe;

Code sample: Detecting a multitouch gesture event


package { import import import import import import import flash.display.Graphics; flash.display.Sprite; flash.events.TouchEvent; flash.events.TransformGestureEvent; flash.ui.Multitouch; flash.ui.MultitouchInputMode; flash.utils.Dictionary;

[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class MultiTouchDemo extends Sprite { private var lineColors:Array = [0x731931, 0x401323, 0x262226, 0x54594C, 0x888C65]; private var lines:Dictionary = new Dictionary(); private var touchPointCount:int = 0; public function MultiTouchDemo() { Multitouch.inputMode = MultitouchInputMode.TOUCH_POINT; addEventListener(TouchEvent.TOUCH_BEGIN, onTouchBegin); addEventListener(TouchEvent.TOUCH_MOVE, onTouchMove); addEventListener(TouchEvent.TOUCH_END, onTouchEnd); } public function onTouchBegin(event:TouchEvent):void { var tPoint:Sprite = new Sprite(); addChild(tPoint); tPoint.graphics.lineStyle(5, lineColors[touchPointCount]); tPoint.graphics.moveTo( event.localX , event.localY); touchPointCount++; lines[event.touchPointID] = tPoint;

104

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

} public function onTouchMove(event:TouchEvent):void { var tPoint:Sprite = lines[event.touchPointID] as Sprite; tPoint.graphics.lineTo(event.localX, event.localY); } public function onTouchEnd(event:TouchEvent):void { var tPoint:Sprite = lines[event.touchPointID] as Sprite; this.removeChild(tPoint); touchPointCount--; delete lines[event.touchPointID]; } }

Code sample: Detecting a rotation gesture event


package { import import import import flash.display.Sprite; flash.events.TransformGestureEvent; flash.ui.Multitouch; flash.ui.MultitouchInputMode

[SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class RotateDemo extends Sprite { private var _rotateMe:Sprite = new Sprite(); public function RotateDemo() { Multitouch.inputMode = MultitouchInputMode.GESTURE; _rotateMe.graphics.lineStyle(1,0x83A603); _rotateMe.graphics.beginFill(0xE9D303); _rotateMe.graphics.drawRoundRect(0,0,100,100,20); _rotateMe.graphics.endFill(); _rotateMe.x = (stage.stageWidth - rotateMe.width) /2; _rotateMe.y = (stage.stageHeight - rotateMe.height) /2; addChild(rotateMe); } rotateMe.addEventListener( TransformGestureEvent.GESTURE_ROTATE, onRotate );

public function onRotate(event:TransformGestureEvent):void { _rotateMe.rotation += event.rotation;

105

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Code sample: Detecting an orientation change event


package { import flash.display.Sprite; import flash.events.AccelerometerEvent; import flash.sensors.Accelerometer; import qnx.ui.text.Label; [SWF(width="1024", height="600", backgroundColor="#cccccc", frameRate="30")] public class OrientationDemo extends Sprite { private var lblStatus:Label = new Label(); public function OrientationDemo() { lblStatus.width = stage.stageWidth; addChild(lblStatus); var accel:Accelerometer = new Accelerometer(); accel.addEventListener(AccelerometerEvent.UPDATE, onUpdate);

private function onUpdate(event:AccelerometerEvent):void { var strStatus:String; if( event.accelerationX > 0.5 ) { strStatus = "Device orientation: Left side up"; } else if( event.accelerationX < -0.5 ) { strStatus = "Device orientation: Right side up"; } else if( event.accelerationY > 0.5 ) { strStatus = "Device orientation: Standing"; } else if( event.accelerationY < -0.5 ) { strStatus = "Device orientation: Standing upside down"; } else if( event.accelerationZ > 0.5 ) { strStatus = "Device orientation: Face up"; } else if( event.accelerationZ < -0.5 ) {

106

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

} } } }

strStatus = "Device orientation: Face down";

lblStatus.text = strStatus;

107

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Signing your application

Before you can distribute your application for use on a BlackBerry PlayBook tablet, you must sign your application. The signing tool included with the BlackBerry Tablet OS SDK adds cryptographic hash values to your application package (BAR file) during the signing process. The hash files help verify the authorship of your application to users and the BlackBerry Tablet OS. There are two phases in the signing process. In the first phase, you configure the your computer to sign applications. To configure your computer: 1. Request permission to sign BlackBerry Tablet OS applications by completing the web form at https:// www.blackberry.com/SignedKeys. After your application is accepted, you receive a CSJ registration file by email. 2. Initialize communication with the RIM Signing Authority. 3. Register with the RIM Signing Authority using your CSJ registration file. 4. Ensure that you have a Developer Certificate. You can use the signing tool to create a Developer Certificate, or provide an existing Developer Certificate from another source. If you create a Developer Certificate using the signing tools, ensure that the common name (company name) parameter matches what you enter in the Company field on the registration form. If you have an existing Developer Certificate you use to sign your Adobe Flash applications, ensure that the name you enter in the Company field on the registration form matches the common name (company name) of your existing certificate. You will not be able to sign your BlackBerry Tablet OS Application if these names do not match. In the second phase of the signing process, you sign your application. To sign your application: 1. Request a BAR file signature for your application from the RIM Signing Authority. 2. Apply your signature to the BAR file using your Developer Certificate. After you sign your application, you can publish it to BlackBerry App World.

108

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

109

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Configure application signing from the command line


Before you begin: Request permission to sign BlackBerry Tablet OS applications by completing the web form at https://www.blackberry.com/SignedKeys. After your application is accepted, you receive a CSJ registration file by email. 1. Initialize communication with the RIM Signing Authority by using the blackberry-signer tool. The following command creates a barsigner.csk file.The blackberry-signer tool writes this file to one of the following locations: Operating system Microsoft Windows Mac OS X Linux barsigner.csk location C:\Documents and Settings\<your_user_name>\Local Settings \Application Data\Research In Motion ~/Library/Research In Motion ~/.rim

The password you specify in the -storepass parameter allows you to access the RIM Signing Authority using your credentials. You should protect the password.
blackberry-signer -csksetup -cskpass <create_a_password>

2.

Register with the RIM Signing Authority using your CSJ registration file. After the blackberry-signer tool successfully registers your CSJ file, the tool adds an entry to the barsigner.db file.
blackberry-signer -register -csjpin <PIN> -cskpass <csk password from step 2> <CSJ_file>

3.

blackberry-keytool tool.

If you already have a Developer Certificate, go to step 2. Otherwise, create a Developer Certificate by using the

The following command creates a Developer Certificate in the p12 file named output_file.p12. The password you specify in the -storepass parameter allows you to access the p12 file. You should protect the p12 file and its password. The value for cn in the dname parameter must match exactly: the name you entered in the Company field on the web form to request permission to sign applications the publisher element in your blackberry-tablet.xml file
blackberry-keytool -genkeypair -keystore <output_file.p12> -storepass <create_a_password> -dname "cn=<company_name>" -alias author

For more information about the command line tools used in this task, please see Command line parameters for the blackberry-keytool tool, and Command line parameters for the blackberry-signer tool.

Package your application from the command line


Before you begin:
110

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Add the path to the bin subfolder where you installed the BlackBerry Tablet OS SDK to the PATH environment variable for your operating system. 1. 2. 3. Open a command prompt. Navigate to the folder where your SWF application and XML configuration files are stored. Type the following command to package your application.
blackberry-airpackager -package output_filename project_name-app.xml project_name.swf any_other_project_files

For more information about command line options, run blackberry-airpackager from the command line with no options.

Sign your application from the command line


After you package your application into a BAR file you can sign it. You must sign your application before you publish it. Before you begin: Package your application into a BAR file. For more information about packaging your application, see Package your application from the command line. Configure your computer to sign applications. For more information about configuring you computer to sign applications, see Configure application signing from the command line. 1. Ask the RIM Signing Authority to sign your BAR file.
blackberry-signer -verbose -cskpass <your CSK password> -keystore <your P12 file> -storepass <your P12 file password> <BAR_file.bar> RDK

2.

Sign the BAR file using your code signing certificate.


blackberry-signer -keystore <your P12 file> -storepass <your p12 file password> <BAR_file.bar> author

Your BAR file contains your signed application. You can publish the BAR file to BlackBerry App World for distribution. For more information about distributing your applications through BlackBerry App World, see the Vendor Portal Administration Guide.

111

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Provide feedback
To provide feedback on this deliverable, visit www.blackberry.com/docsfeedback.

112

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

Legal notice

10

2011 Research In Motion Limited. All rights reserved. BlackBerry, RIM, Research In Motion, and related trademarks, names, and logos are the property of Research In Motion Limited and are registered and/or used in the U.S. and countries around the world. Adobe,AIR, Flash, and ActionScript are trademarks of Adobe Systems Incorporated. SQLite is a trademark of Hipp, Wyrick & Company, Inc. QNX is a trademark of QNX Software Systems GMBH & Co. All other trademarks are the property of their respective owners. This documentation including all documentation incorporated by reference herein such as documentation provided or made available at www.blackberry.com/go/docs is provided or made accessible "AS IS" and "AS AVAILABLE" and without condition, endorsement, guarantee, representation, or warranty of any kind by Research In Motion Limited and its affiliated companies ("RIM") and RIM assumes no responsibility for any typographical, technical, or other inaccuracies, errors, or omissions in this documentation. In order to protect RIM proprietary and confidential information and/or trade secrets, this documentation may describe some aspects of RIM technology in generalized terms. RIM reserves the right to periodically change information that is contained in this documentation; however, RIM makes no commitment to provide any such changes, updates, enhancements, or other additions to this documentation to you in a timely manner or at all. This documentation might contain references to third-party sources of information, hardware or software, products or services including components and content such as content protected by copyright and/or third-party web sites (collectively the "Third Party Products and Services"). RIM does not control, and is not responsible for, any Third Party Products and Services including, without limitation the content, accuracy, copyright compliance, compatibility, performance, trustworthiness, legality, decency, links, or any other aspect of Third Party Products and Services. The inclusion of a reference to Third Party Products and Services in this documentation does not imply endorsement by RIM of the Third Party Products and Services or the third party in any way. EXCEPT TO THE EXTENT SPECIFICALLY PROHIBITED BY APPLICABLE LAW IN YOUR JURISDICTION, ALL CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS, OR WARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY CONDITIONS, ENDORSEMENTS, GUARANTEES, REPRESENTATIONS OR WARRANTIES OF DURABILITY, FITNESS FOR A PARTICULAR PURPOSE OR USE, MERCHANTABILITY, MERCHANTABLE QUALITY, NON-INFRINGEMENT, SATISFACTORY QUALITY, OR TITLE, OR ARISING FROM A STATUTE OR CUSTOM OR A COURSE OF DEALING OR USAGE OF TRADE, OR RELATED TO THE DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NON-PERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES REFERENCED HEREIN, ARE HEREBY EXCLUDED. YOU MAY ALSO HAVE OTHER RIGHTS THAT VARY BY STATE OR PROVINCE. SOME JURISDICTIONS MAY NOT ALLOW THE EXCLUSION OR LIMITATION OF IMPLIED WARRANTIES AND CONDITIONS. TO THE EXTENT PERMITTED BY LAW, ANY IMPLIED WARRANTIES OR CONDITIONS RELATING TO THE DOCUMENTATION TO THE EXTENT THEY CANNOT BE EXCLUDED AS SET OUT ABOVE, BUT CAN BE LIMITED, ARE HEREBY LIMITED TO NINETY (90) DAYS FROM THE DATE YOU FIRST ACQUIRED THE DOCUMENTATION OR THE ITEM THAT IS THE SUBJECT OF THE CLAIM. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, IN NO EVENT SHALL RIM BE LIABLE FOR ANY TYPE OF DAMAGES RELATED TO THIS DOCUMENTATION OR ITS USE, OR PERFORMANCE OR NONPERFORMANCE OF ANY SOFTWARE, HARDWARE, SERVICE, OR ANY THIRD PARTY PRODUCTS AND SERVICES

113

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

REFERENCED HEREIN INCLUDING WITHOUT LIMITATION ANY OF THE FOLLOWING DAMAGES: DIRECT, CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, INDIRECT, SPECIAL, PUNITIVE, OR AGGRAVATED DAMAGES, DAMAGES FOR LOSS OF PROFITS OR REVENUES, FAILURE TO REALIZE ANY EXPECTED SAVINGS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, LOSS OF BUSINESS OPPORTUNITY, OR CORRUPTION OR LOSS OF DATA, FAILURES TO TRANSMIT OR RECEIVE ANY DATA, PROBLEMS ASSOCIATED WITH ANY APPLICATIONS USED IN CONJUNCTION WITH RIM PRODUCTS OR SERVICES, DOWNTIME COSTS, LOSS OF THE USE OF RIM PRODUCTS OR SERVICES OR ANY PORTION THEREOF OR OF ANY AIRTIME SERVICES, COST OF SUBSTITUTE GOODS, COSTS OF COVER, FACILITIES OR SERVICES, COST OF CAPITAL, OR OTHER SIMILAR PECUNIARY LOSSES, WHETHER OR NOT SUCH DAMAGES WERE FORESEEN OR UNFORESEEN, AND EVEN IF RIM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW IN YOUR JURISDICTION, RIM SHALL HAVE NO OTHER OBLIGATION, DUTY, OR LIABILITY WHATSOEVER IN CONTRACT, TORT, OR OTHERWISE TO YOU INCLUDING ANY LIABILITY FOR NEGLIGENCE OR STRICT LIABILITY. THE LIMITATIONS, EXCLUSIONS, AND DISCLAIMERS HEREIN SHALL APPLY: (A) IRRESPECTIVE OF THE NATURE OF THE CAUSE OF ACTION, DEMAND, OR ACTION BY YOU INCLUDING BUT NOT LIMITED TO BREACH OF CONTRACT, NEGLIGENCE, TORT, STRICT LIABILITY OR ANY OTHER LEGAL THEORY AND SHALL SURVIVE A FUNDAMENTAL BREACH OR BREACHES OR THE FAILURE OF THE ESSENTIAL PURPOSE OF THIS AGREEMENT OR OF ANY REMEDY CONTAINED HEREIN; AND (B) TO RIM AND ITS AFFILIATED COMPANIES, THEIR SUCCESSORS, ASSIGNS, AGENTS, SUPPLIERS (INCLUDING AIRTIME SERVICE PROVIDERS), AUTHORIZED RIM DISTRIBUTORS (ALSO INCLUDING AIRTIME SERVICE PROVIDERS) AND THEIR RESPECTIVE DIRECTORS, EMPLOYEES, AND INDEPENDENT CONTRACTORS. IN ADDITION TO THE LIMITATIONS AND EXCLUSIONS SET OUT ABOVE, IN NO EVENT SHALL ANY DIRECTOR, EMPLOYEE, AGENT, DISTRIBUTOR, SUPPLIER, INDEPENDENT CONTRACTOR OF RIM OR ANY AFFILIATES OF RIM HAVE ANY LIABILITY ARISING FROM OR RELATED TO THE DOCUMENTATION. Prior to subscribing for, installing, or using any Third Party Products and Services, it is your responsibility to ensure that your airtime service provider has agreed to support all of their features. Some airtime service providers might not offer Internet browsing functionality with a subscription to the BlackBerry Internet Service. Check with your service provider for availability, roaming arrangements, service plans and features. Installation or use of Third Party Products and Services with RIM's products and services may require one or more patent, trademark, copyright, or other licenses in order to avoid infringement or violation of third party rights. You are solely responsible for determining whether to use Third Party Products and Services and if any third party licenses are required to do so. If required you are responsible for acquiring them. You should not install or use Third Party Products and Services until all necessary licenses have been acquired. Any Third Party Products and Services that are provided with RIM's products and services are provided as a convenience to you and are provided "AS IS" with no express or implied conditions, endorsements, guarantees, representations, or warranties of any kind by RIM and RIM assumes no liability whatsoever, in relation thereto. Your use of Third Party Products and Services shall be governed by and subject to you agreeing to the terms of separate licenses and other agreements applicable thereto with third parties, except to the extent expressly covered by a license or other agreement with RIM. Certain features outlined in this documentation require a minimum version of BlackBerry Enterprise Server, BlackBerry Desktop Software, and/or BlackBerry Device Software.

114

RIM Confidential and Proprietary Information - Beta Customers Only. Content and software are subject to change.

The terms of use of any RIM product or service are set out in a separate license or other agreement with RIM applicable thereto. NOTHING IN THIS DOCUMENTATION IS INTENDED TO SUPERSEDE ANY EXPRESS WRITTEN AGREEMENTS OR WARRANTIES PROVIDED BY RIM FOR PORTIONS OF ANY RIM PRODUCT OR SERVICE OTHER THAN THIS DOCUMENTATION. Research In Motion Limited 295 Phillip Street Waterloo, ON N2L 3W8 Canada Research In Motion UK Limited Centrum House 36 Station Road Egham, Surrey TW20 9LF United Kingdom Published in Canada

115

You might also like