Posts tagged "tips and tricks"

AIR for TV Stage property settings

In my last blog entry discussing a TV’s safe viewing area, I mentioned the Stage.stageWidth and Stage.stageHeight properties of a full-screen application on a TV with a 1080p screen resolution.  Let’s look a little more at how to set these and other Stage properties with regard to AIR for TV apps.

Stage.stageWidth and Stage.stageHeight

If you are writing a full-screen AIR for TV application for a specific device, go ahead and  hard-code Stage.stageWidth and Stage.stageHeight to the device’s screen resolution. However, to write a full-screen application that runs on multiple devices, use the Capabilities.screenResolutionX and Capabilities.screenResolutionY properties to set your Stage dimensions. For example:

stage.stageWidth = Capabilities.screenResolutionX;
stage.stageHeight = Capabilities.screenResolutionY;

Stage scale mode

Set Stage.scaleMode to StageScaleMode.NO_SCALE, and listen for stage resize events.

stage.scaleMode = StageScaleMode.NO_SCALE;
stage.addEventListener(Event.RESIZE, layoutHandler);

This scale mode setting results in the following:

  • When the application’s window changes size, the stage contents maintain their defined size. The runtime performs no automatic layout or scaling. Also, the runtime dispatches the Stage class’s resize event. Therefore, you have full control over how to adjust the application’s contents when the application begins and when the application window resizes.
  • You can use the stageWidth and stageHeight properties of the Stage class to determine the actual pixel dimensions of the application’s window. Therefore, in full-screen applications, these properties correspond to the screenResolutionX and screenResolutionY properties of the Capabilities class.

Stage alignment

Set Stage.align to StageAlign.TOP_LEFT:

stage.align = StageAlign.TOP_LEFT;

This alignment places the 0,0 coordinate in the upper-left corner of the screen, which is convenient for content placement using ActionScript. Therefore, this alignment works nicely with StageScaleMode.NO_SCALE, since your application is in charge of layout.

Stage display state

Set Stage.displayState in a full-screen AIR for TV application to StageDisplayState.FULL_SCREEN_INTERACTIVE:

stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;

This value sets the AIR application to expand the stage over the entire screen, with user input allowed.

Stage quality

You can set the Stage.quality property for an AIR for TV application to StageQuality.Best or StageQuality.High, specifying the rendering quality for all Stage objects. For example:

stage.quality = StageQuality.High;

AIR for TV applications and the “safe viewing area” (aka “title safe area”)

Here’s another design consideration for AIR for TV applications.  (This and other tips will be incorporated soon into Adobe online documentation).

When designing your user interface for an AIR for TV app, be sure to consider the safe viewing area. The safe viewing area on a TV is the area of the screen that the end-user can actually see. This area is also known as the title safe area. Overscan is the portion of the actual image area that falls outside the safe viewing area. The safe viewing area can vary depending on the device. This concept originated with analog televisions in which the television’s physical design sometimes hid the edges of the displayed image. However, it still often applies today.

Adobe recommends an inset of 7.5% on each edge of the screen. For example, on a TV with a screen resolution of 1080p, a full-screen AIR application has a Stage.stageWidth of 1920 and Stage.stageHeight of 1080. The following figure shows the safe viewing area of the stage using 7.5%:

I’ll leave it to you to do the math for 7.5% for other screen resolutions such as 540p and 720p (stage dimensions of 960 x 540 and 1280 x 720, respectively).

Because of the safe viewing area, design your full-screen AIR for TV application as follows:

  • Use the entire stage dimensions for backgrounds, such as background images or background colors.
  • Use only the safe viewing area for critical application elements such as text, graphics, video, and user interface items such as buttons.

Depending on the device on which your application runs, the safe viewing area sometimes doesn’t apply. But to be sure your critical application elements are never hidden, always design to accommodate the safe viewing area.

The StageVideo article for you

If you are developing applications for AIR 2.5 for TV or for Flash Player 10.1 Beta for GoogleTV, be sure to visit this Adobe Developer Connection article to learn about using the StageVideo class:

Delivering video and content for the Flash Platform on TV

But if you are developing applications for Flash Player 10.2 Beta, see this article instead:

Getting started with stage video

The main difference is in the events that get dispatched. Flash Player 10.2 Beta provides the StageVideoAvailabilityEvent, the StageVideoEvent, and the VideoEvent.
AIR 2.5 for TV and Flash Player 10.1 Beta for GoogleTV dispatch only the StageVideoEvent.

The importance of providing an update mechanism in an AIR application

Applications provide updates for many reasons, including bug fixes, security patches, and new functionality. This holds true for AIR applications as well.

Adobe ships occasional update versions of Adobe AIR. And Adobe AIR applications can take advantage of new features and bug fixes in new versions of the runtime.

Also, new versions of Adobe AIR may include updated versions of WebKit (the HTML rendering engine in AIR). This may change the behavior or appearance of HTML content in an AIR application. For example, improvements or corrections in WebKit may change the layout of HTML elements in an AIR application’s user interface.

It is important to provide an update mechanism in your application. When you update your application, the application can inform the user of the new update version. Should you need to update your application due to a change in the WebKit version included in AIR, the update mechanism will let your users know about the new version of your application.

AIR includes a update framework, which simplifies the task of managing update versions and adding appropriate user interface in your AIR application.

For more information, see “Updating AIR applications” in the AIR developer’s guides:

Also, these “Quick Start” sample applications show how to use the update framework:

DataProvider.getItemIndex()

A user recently asked why the call to DataProvider.getItemIndex() in the following example returns -1:

import fl.controls.List;
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
dp.addItem({label:"AL", data:"Montgomery"});
dp.addItem({label:"AK", data:"Juneau"});
dp.addItem({label:"AR", data:"Little Rock"});
// assign the data provider to the list
var myList:List = new List();
myList.dataProvider = dp;
myList.rowHeight = 35;
myList.rowCount = dp.length;
myList.move(10, 10);
addChild(myList);	// display the list
// this attempt to locate an item in the list returns -1
trace("Index is: " + myList.dataProvider.getItemIndex({label:"AK", data:"Juneau"}));

Paul Robertson explains:

The problem is that the getItemIndex() method matches exact object references, not objects with matching properties. The first object, {label:”AK”, data”Juneau”}, may
have identical property values with the one that’s being passed to the getItemIndex() method, but they’re not exactly the same object – they’re just two different objects that happen to have the same property values.

To get a match with getItemIndex(), you need to pass a reference to the actual object that’s in the data provider. To do that, of course, you need a reference to the
same object, for example in a variable. Here’s a variation of your code that works:

import fl.controls.List;
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
var item1:Object = {label:"AL", data:"Montgomery"};
var item2:Object = {label:"AK", data:"Juneau"};
var item3:Object = {label:"AR", data:"Little Rock"};
dp.addItem(item1);
dp.addItem(item2);
dp.addItem(item3);
var myList:List = new List();
myList.dataProvider = dp;
myList.rowHeight = 35;
myList.rowCount = dp.length;
myList.move(10, 10);
addChild(myList);
trace("Index is: " + myList.dataProvider.getItemIndex(item2));

Of course, you are probably really trying to do some sort of search to find the index of an item that matches a user entered string. The only way I can see to do that is to loop over the data provider one item at a time and compare the property values. You can either loop over the data provider directly using dp.length and
dp.getItemAt(index), or else keep the objects in a separate array. This code demonstrates the first approach:

import fl.controls.List;
import fl.controls.Button;
import fl.controls.TextInput;
import fl.data.DataProvider;
var dp:DataProvider = new DataProvider();
dp.addItem({label:"AL", data:"Montgomery"});
dp.addItem({label:"AK", data:"Juneau"});
dp.addItem({label:"AR", data:"Little Rock"});
var myList:List = new List();
myList.dataProvider = dp;
myList.rowHeight = 35;
myList.rowCount = dp.length;
myList.move(10, 35);
addChild(myList);
var ti:TextInput = new TextInput();
ti.width = 100;
ti.move(10, 10);
addChild(ti);
var btn:Button = new Button();
btn.width = 50;
btn.label = "Search";
btn.move(120, 10);
addChild(btn);
btn.addEventListener(MouseEvent.CLICK, btn_click);
function btn_click(event:Event):void
{
for (var i:int = 0, len:int = dp.length; i < len; i++)
{
if (dp.getItemAt(i).data == ti.text)
{
trace("Index is: " + i.toString());
return;
}
}
trace("Item not found");
}