Inline item renderers These types of item renderers are still rather simple to implement, but they allowyou to exert more control over the component.. For example, with a drop-in itemren
Trang 1You’ll notice that in this example, both data grids havedropEnabledanddragEnabledset totrue This in and of itself allows the user to copy contents from one data grid
to the other However, as shown in Example 8-8, this does not ensure the type ofbehavior required in this case To achieve the move-only behavior, each data gridalso listens fordragCompleteevents ThedragCompleteHandler( )method handles theevents by either dismissing the event if the event action is set tonone, or deleting theelement from the drag initiator’s data provider
Custom Drag and Drop Operations
The built-in drag and drop functionality will work for many use cases However,there are also many use cases in which you will want to employ drag and drop func-tionality not supported by the standard, built-in features of the handful of drag anddrop-enabled components For these cases, you can create custom drag and dropelements
You can create custom drag and drop elements using the events discussed in the ceding section in conjunction with mx.managers.DragManager TheDragManagerclasshas several static methods you can use to handle drag and drop functionality
pre-ThedoDrag( )method allows you to start a drag and drop operation The doDrag( )method requires that you specify the following parameters: the drag initiator, aDragSourceobject specifying the data to copy from the initiator, and the mouse eventused to start the drag operation In addition, in most cases you’ll need to pass it a ref-erence to an object to use as the drag proxy image (the object that actually drags).Before we look at an example usingdoDrag( )let’s first discuss the details of workingwithDragSource TheDragSourceobject you pass todoDrag( )is what is passed along
to event handlers for drag events This object contains data that you can use whencopying, moving, or comparing That means you should generally store whateverdata you want to pass along to the drag event handlers in the DragSource object.DragSourceobjects allow you to save many groups of data, each with a unique key (a
string value) called a format You can use the addData( ) method to add data to aDragSourceobject The first parameter is the data to store, and the second parameter
is the format, which is an arbitrary string:
var dragSource:DragSource = new DragSource( );
Trang 2Drag and Drop | 171
proxy indicates that it cannot be dropped successfully by displaying a small red circlewith a white X You can remove that icon by callingDragManager.acceptDragDrop( )and passing it a reference to the drop target on which the user can drop the object.Typically you call this method in response to adragEnter event
Example 8-10 illustrates how to create custom drag and drop elements This simpleapplication uses a column of colored canvases and a grid of canvases with the samecolors The canvases from the column are draggable When the user drops one can-vas over the other with the same color in the grid, the canvas is removed from thecolumn, and the canvas in the grid is lowered in opacity
Example 8-10 A customized drag and drop application
private function beginDragAndDrop(event:MouseEvent):void {
var canvas:Canvas = Canvas(event.currentTarget);
var dragSource:DragSource = new DragSource( );
var color:uint = canvas.getStyle("backgroundColor");
private function dragEnterHandler(event:DragEvent):void {
var target:Canvas = Canvas(event.currentTarget);
var initiator:Canvas = Canvas(event.dragInitiator);
if(matches(target, initiator)) {
DragManager.acceptDragDrop(target);
}
}
private function dragDropHandler(event:DragEvent):void {
var target:Canvas = Canvas(event.currentTarget);
var initiator:Canvas = Canvas(event.dragInitiator);
Trang 3Customizing List-Based Controls
List-based controls such as lists, data grids, and trees have standard ways in whichthey display data For example, a list displays one column of text, data grids displayone or more columns of text, and trees display a hierarchical view of data For many
if not most applications, the default ways in which these controls display data are
return a.getStyle("backgroundColor") == b.getStyle("backgroundColor");
}
]]>
</mx:Script>
<mx:HBox width="100%">
<mx:VBox id="vbox" height="100%">
<mx:Canvas width="50" height="50" backgroundColor="#00ff80"
<mx:GridRow width="100%" height="100%">
<mx:GridItem width="100%" height="100%">
<mx:Canvas width="50" height="50" backgroundColor="#00ff80"
dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:Canvas width="50" height="50" backgroundColor="#ff8040"
dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)" />
</mx:GridItem>
</mx:GridRow>
<mx:GridRow width="100%" height="100%">
<mx:GridItem width="100%" height="100%">
<mx:Canvas width="50" height="50" backgroundColor="#80ffff"
dragEnter="dragEnterHandler(event)" dragDrop="dragDropHandler(event)" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:Canvas width="50" height="50" backgroundColor="#ffff80"
Trang 4Customizing List-Based Controls | 173
perfectly sufficient However, there are cases in which you need to alter the displays
in one way or another For example, you may want to display a checkbox in a datagrid column rather than standard text
When you want to customize the way in which a list-based component displays
ele-ments, you can use what is called an item renderer Item renderers allow you to
spec-ify what component to use in place of the standard text or text and icon that appear
in the component, thus customizing the appearance of the elements in the
HorizontalList,DataGrid,Menu,TileList, andTree
There are two basic ways to use custom item renderers:
Drop-in item renderers
These are the simplest types of item renderers to implement With a drop-initem renderer, you simply specify a standard UI component to use in a particu-lar column For example, you can use a checkbox as a drop-in item renderer
Inline item renderers
These types of item renderers are still rather simple to implement, but they allowyou to exert more control over the component For example, with a drop-in itemrenderer, you cannot specify the property settings for the component, but with
an inline item renderer you can
You can use standard or custom components as item renderers with either of theseapproaches
Drop-In Item Renderers
Drop-in item renderers are extremely simple to implement All you need to do is setthe itemRendererproperty of the component for which you want to customize theitem views The itemRendererproperty should be a reference to a component classyou want to use For example, the following creates a list component that uses a datefield component for each item:
<mx:Script>
<![CDATA[
import mx.collections.ArrayCollection;
[Bindable]
private var dataSet:ArrayCollection =
new ArrayCollection([new Date(2010, 1, 1), new Date(2010, 4, 15)]);
]]>
</mx:Script>
<mx:List itemRenderer="mx.controls.DateField" dataProvider="{dataSet}" />
The results of this are shown in Figure 8-1
Trang 5All the list-based components that allow you to use item renderers allow you to setthe itemRenderer property for the component itself, except in the case of the datagrid, which requires that you set the itemRenderer property at the column level.Example 8-11 sets one of the columns of a data grid to display a checkbox.
Figure 8-1 A date field used as an item renderer in a list component
Example 8-11 Using a drop-in item renderer
<mx:DataGridColumn headerText="Song Title" dataField="title"/>
<mx:DataGridColumn headerText="Artist" dataField="artist"/>
<mx:DataGridColumn headerText="In Favorites" dataField="inFavorites"
<mx:Object songId="2" title="Enjoy the Silence"
artist="Depeche Mode" rating="4" />
<mx:Object songId="3" title="Mesopotamia"
artist="B-52s" rating="5" inFavorites="true" />
Trang 6Customizing List-Based Controls | 175
Drop-in item renderers are ideal when you want to use a simple type of item derer However, they have several major limitations:
ren-• You can use only a handful of standard UI components as drop-in item ers Those components you can use are listed in Table 8-2
render-• The data value for an item always corresponds to one property of the item derer In other words, a list-based component is a view for the data modelassigned to the dataProvider property For example, the item value is alwaysassigned to the value of a numeric stepper used as an item renderer You cannotspecify that the item value should be assigned to the maximum property of thenumeric stepper
ren-• You cannot customize the components used as item renderers
Inline Item Renderers
Although drop-in item renderers are extremely simple to implement, they are alsoquite limited in terms of how you can configure them For instance, in Example 8-11you can display the checkbox in the data grid columns, but you cannot change any
of the properties of the components used as item renderers
Inline item renderers are a slight step up from drop-in item renderers in that you canconfigure the settings of the component used as the item renderer For example, youcan use an inline item renderer to set theenabled property of the checkbox to dis-able it so that the user cannot check or uncheck the box
Inline item renderers require that you specify the itemRenderervalue using nestedMXML tags rather than attributes You must then nest within theitemRenderertag aComponenttag with a nested tag to create the type of component you want to use as
an item renderer Example 8-12 specifies the checkbox item renderer as an inlineitem renderer It also applies a label to the checkbox, and it disables the checkbox sothat the user cannot select or deselect it
Table 8-2 Drop-in components
Component Property set by the item value
Trang 7TheComponenttag is a powerful MXML tag It creates an entirely new scope withinthe MXML document The code within the Component tag is essentially an MXMLcomponent, and the rules that apply to MXML components generally apply to thecode within theComponenttag You can have just one root node, and within that rootnode you can use Style, Script, and all standard MXML tags used in an MXMLcomponent document Because theComponent tag creates its own scope, you don’thave to worry about conflicts within the Component tag and the document withinwhich theComponenttag exists However, this also means that you cannot referencedata from the MXML document within theComponenttag For example, the follow-ing will cause a compile error:
<mx:DataGridColumn headerText="Song Title" dataField="title"/>
<mx:DataGridColumn headerText="Artist" dataField="artist"/>
<mx:DataGridColumn headerText="In Favorites" dataField="inFavorites">
artist="Depeche Mode" rating="4" />
<mx:Object songId="3" title="Mesopotamia"
artist="B-52s" rating="5" inFavorites="true" />
Trang 8Customizing List-Based Controls | 177
Although theComponenttag is powerful, we strongly recommend that you use it only
to the extent illustrated by Example 8-12 which sets the label and enabled properties
of the checkbox If you need to create more sophisticated item renderers, it is far ter to define them as MXML or ActionScript components We’ll look at how to dothat in the next section
bet-You can use a property called outerDocument within a Component tag to
reference the MXML document containing the Component tag You can
then reference any public or internal properties, as in the following
However, while this is possible, it is generally not recommended
because it is much clearer to break out sophisticated item renderers
into new custom components, as discussed next.
Custom Components as Item Renderers
In order to exert the most control over item renderers you can use a custom nent Using a custom component (either MXML or ActionScript) you can createextremely sophisticated item renderers For example, you can create an item ren-derer that displays a rating using colored shapes, as we’ll do in this section
compo-A component must implement certain interfaces to work as an item renderer There
IDropInListItemRenderer, and IDataRenderer All item renderers must implement
Trang 9IListItemRenderer and IDataRenderer Because IListItemRenderer extendsIDataRenderer, you simply need to implementIListItemRendererin most cases TheIListItemRenderer interface requires many getter/setter methods and public meth-ods, and the best way to implement the interface is simply to extend a class thatalready implements the interface The following classes already implement the inter-face: Button, ComboBox, Container, DataGridItemRenderer, DateField, Image, Label,ListBase, ListItemRenderer, MenuBarItem, MenuItemRenderer, NumericStepper,TextArea, TextInput, TileListItemRenderer, and TreeItemRenderer BecauseContainer implements the interface, you can extend any type of container.
TheIDataRendererinterface requires that the implementing class defines a data ter and setter of typeObject The data setter is automatically called every time thedata provider is updated and the item renderer needs to update The data setter isalways passed the data provider element corresponding to the item For example, in
get-a dget-atget-a grid the dget-atget-a is the object representing the row Even though your customitem renderer component is likely to inherit the data implementation, you’ll gener-ally want to override that implementation
Example 8-13 is saved in an MXML document called Rating.mxml, and it draws five
squares using 10-by-10 canvases The squares are blue by default, and they are ored red if they are activated by the value of the rating property from the data passed
col-to the component Notice that this component overrides the data getter and setter.The setter retrieves the rating value, and it draws the canvases with the appropriatecolors based on the rating value
Example 8-13 A custom component for use as an item renderer
private var _data:Object;
override public function set data(value:Object):void {
_data = value;
var rating:uint = uint(value.rating);
removeAllChildren( );
var canvas:Canvas;
for(var i:uint = 0; i < 5; i++) {
canvas = new Canvas( );
Trang 10Customizing List-Based Controls | 179
The MXML application document in Example 8-14 uses the custom component as
an item renderer in a data grid using drop-in syntax
Note that if the item renderer MXML or ActionScript class is in a
package, you would specify the fully qualified path to the MXML
doc-ument or class in the itemRenderer property value.
<mx:DataGridColumn headerText="Song Title" dataField="title"/>
<mx:DataGridColumn headerText="Artist" dataField="artist"/>
<mx:DataGridColumn headerText="Rating" dataField="rating"
Trang 11Creating Item Editors
When components are editable, they use standard text inputs when the user is ing a value For example, the following code creates a list with editable values simply
edit-by setting the editable property to true But the user can edit the values only byusing the standard text input when she clicks on an item:
<mx:List editable="true" width="200" labelField="rating">
<mx:Object songId="1" title="Rio" artist="Duran Duran" rating="3" />
<mx:Object songId="2" title="Enjoy the Silence" artist="Depeche Mode"
<mx:List editable="true" width="200" labelField="rating"
<mx:Object songId="1" title="Rio" artist="Duran Duran" rating="3" />
<mx:Object songId="2" title="Enjoy the Silence" artist="Depeche Mode"
Trang 12Customizing List-Based Controls | 181
stepper as the item renderer in the preceding example The user could update thenumeric stepper value used as an item renderer However, item renderers simply ren-der the data They do not create data binding with the data provider Therefore,changing a value in a numeric stepper used as an item renderer will not affect thedata provider, whereas it will update the data provider when used as an item ren-derer However, you can tell a component to use the item renderer as the item editor
by setting therendererIsEditor property totrue:
<mx:List editable="true" width="200" labelField="rating"
<mx:Object songId="1" title="Rio" artist="Duran Duran" rating="3" />
<mx:Object songId="2" title="Enjoy the Silence" artist="Depeche Mode"
Trang 13Example 8-16 usesRating as both the item renderer and the item editor.
private function draw( ):void {
var rating:uint = uint(_data.rating);
removeAllChildren( );
var canvas:Canvas;
for(var i:uint = 0; i < 5; i++) {
canvas = new Canvas( );
canvas.setStyle("backgroundColor", i < rating ? 0xFF0000 : 0x0000FF); canvas.width = 10;
<mx:DataGridColumn headerText="Song Title" dataField="title"/>
<mx:DataGridColumn headerText="Artist" dataField="artist"/>
<mx:DataGridColumn headerText="Rating" dataField="rating"
itemRenderer="Rating" rendererIsEditor="true" editorDataField="data" />
Trang 14Focus Management and Keyboard Control | 183
Focus Management and Keyboard Control
Focus management and keyboard control are two related topics in Flex An object
has focus when it can respond to keyboard events For example, when a text input
control has focus, the user can enter text into the field When a component hasfocus, it generally indicates that focus with a colored border You can use the key-board to control focus within a Flex application, and you can also respond to keypresses We’ll look at all of these topics in the next few sections
Controlling Tab Order
A standard application convention is that pressing the Tab key advances the focus tothe next element, and Shift-Tab moves focus to the preceding element This is true ofmost desktop applications It is true of most HTML applications And it is also true
of Flex applications
Many (though certainly not all) Flex components are capable of receiving focus Forexample, text inputs, combo boxes, and buttons are all capable of receiving focus.Clearly there are other types of components that cannot receive focus For example,
aVBoxcontainer, a label, or a spacer cannot receive focus because none of these ponents can respond to keyboard input
com-When several focus-enabled components exist on the screen at the same time, thereexists a default order by which the user can move focus by pressing the Tab key Theorder always moves from left to right, top to bottom The following code creates aform with three text inputs and a button The first two text inputs are side by side onthe same line, the next text input follows on the next line, and that is followed by thebutton on the next line In this example, if the user places focus in thefirstNametextinput and presses Tab, the focus next moves to thelastNametext field Another press
of the Tab key, and focus shifts to theemailtext input on the next line Finally, onemore Tab key press, and focus moves to the button
Trang 15shifts focus from component to component in a circular or looping fashion.
Although the default order of elements in a tab loop is generally what you wouldwant and what a user of the application would expect, there are exceptions Forthose exceptions, you can control the order of the elements in a tab loop by specify-ingtabIndexproperty values Every focus-enabled component has a tabIndexprop-erty By default, the properties are null, and Flex applications use the default taborder However, you can explicitly define the order of the elements in a tab loop byspecifying integer values starting with 1 for thetabIndexproperties of all the compo-nents in a tab loop The following example illustrates how this works with textinputs arranged in a grid By default, the order would go from left to right, top tobottom In this case, we’re setting thetabIndexproperties so that the order is fromtop to bottom, left to right
<mx:Grid>
<mx:GridRow width="100%" height="100%">
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="a" tabIndex="1" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="c" tabIndex="3" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="e" tabIndex="5" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="g" tabIndex="7" />
</mx:GridItem>
</mx:GridRow>
<mx:GridRow width="100%" height="100%">
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="b" tabIndex="2" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="d" tabIndex="4" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="f" tabIndex="6" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
Trang 16Focus Management and Keyboard Control | 185
<mx:TextInput id="h" tabIndex="8" />
</mx:GridItem>
</mx:GridRow>
</mx:Grid>
Note that the behavior of tab order can be unpredictable if you set one
or more, but not all, of the tabIndex properties for the components in
a tab loop Generally you should either use the default tab order or set
the tabIndex for all the components in a tab loop.
Although focus-enabled components are included in the tab order by default, youcan explicitly exclude them by setting their tabEnabled property to false SettingtabEnabled to false does not mean the component cannot receive focus program-matically or when the user clicks on it with the mouse However, it does mean that itwill not be included in the tab loop
If you want to exclude all the child components of a container from a tab loop, ply set thetabChildrenproperty of the container tofalse That has the same effect assettingtabEnabled tofalse for each of the child controls
sim-Programmatically Controlling Focus
instance AFocusManagerinstance controls one tab loop, and at one point there mayexist multiple tab loops per application This is so that some containers are capable
of creating their own tab loops For example, a pop-up window might have its owntab loop, distinct from the tab loop in a form behind the window Because severaltab loops might contain elements visible at the same time, a Flex application canhave more than oneFocusManager in use at any one time
You never have to construct a new FocusManagerinstance Every component has afocusManagerproperty that references theFocusManagerinstance that controls the tabloop to which the component belongs
You can programmatically retrieve the focused item using thegetFocus( )method of aFocusManagerinstance ThegetFocus( )method returns the component that currentlyhas focus typed asIFocusManagerComponent You should cast the return ofgetFocus( )when necessary Unlike lower-level Flash Player APIs for focus management, thegetFocus( )method of aFocusManagerinstance always returns a reference to the actualcomponent that has focus, not a raw child object of the component For example,from a Flash Player perspective, when a text input control has focus, it is really thenested lower-level text field that has focus Yet from a practical standpoint, you areusually interested in the component that has focus, not its subelements
You can set focus using thesetFocus( ) method of aFocusManager object You canpass setFocus( ) a reference to any focus-enabled component For example, the
Trang 17following code resets the values of the text input controls and then moves focus tothe first text input when the user clicks the button.
<mx:GridRow width="100%" height="100%">
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="a" tabIndex="1" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="c" tabIndex="3" />
</mx:GridItem>
</mx:GridRow>
<mx:GridRow width="100%" height="100%">
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="b" tabIndex="2" />
</mx:GridItem>
<mx:GridItem width="100%" height="100%">
<mx:TextInput id="d" tabIndex="4" />
Responding to Keyboard Events
You can listen for keyboard events much like you can listen for any other sort ofevent using inline MXML attributes and/or ActionScript All display objects,including all controls, containers, and the stage itself, dispatch events of typeflash events.KeyboardEventwhen the user presses a key on the keyboard There are twodistinct events with each key press:keyUpandkeyDown, which are represented by theKeyboardEvent.KEY_UP andKeyboardEvent.KEY_DOWN constants
TheKeyboardEventtype defines several properties specific to the event Among thoseproperties is the keyCode property, which contains the code of the key that waspressed, and thecharCodeproperty, which contains the code of the specific charac-ter The keyCode and charCode properties are the same for all alphanumeric keys
Trang 18Focus Management and Keyboard Control | 187
when they are not Shifted, Ctrl’d, or Alt’d For alphanumeric keys, the key and acter codes are the ASCII codes
char-Theflash.ui.Keyboardclass defines constants that you can use for comparisons withkey codes for nonalphanumeric keys For example, Keyboard.ENTER and Keyboard SHIFT contain the key code values for the Enter and Shift keys
Components dispatch keyboard events only when they have focus Example 8-17 usesthis fact to create a simple context-based help system for a form in an application
Example 8-17 A simple keyboard event example
private var _helpWindow:TitleWindow;
private function keyUpHandler(event:KeyboardEvent):void {
else if(event.currentTarget == lastName) {
textArea.text = "Specify your last name, e.g Smith";
}
else if(event.currentTarget == email) {
textArea.text = "Specify your email address, e.g bob@yahoo.com";
}
else if(event.currentTarget == accountType) {
textArea.text = "Select an account type from the drop-down";
}
else {
textArea.text = "Generic application help";
}
Trang 19In Example 8-17, the user can press F1, and a help window will appear with helpspecific to the control that has focus.
The KeyboardEvent class also defines the Boolean properties ctrlKey, altKey, andshiftKey, which tell you whether the user is pressing the Ctrl, Alt, or Shift keys Thefollowing rewrite to the if statement for Example 8-17 causes the help to appearonly when the user presses Ctrl-F1:
if(event.keyCode == Keyboard.F1 && event.ctrlKey) {
If you want to listen to events globally within an application, add listeners to theapplication container:
this.addEventListener(KeyboardEvent.KEY_DOWN, keyUpHandler);
Summary
In this chapter, we discussed a variety of topics spanning the gamut of frameworkutilities and advanced component concepts These topics included working withFlex tool tips, adding pop ups, managing the cursor, adding drag and drop behavior,customizing list-based components, and focus management and keyboard control
<mx:FormItem label="First Name">
<mx:TextInput id="firstName" keyUp="keyUpHandler(event)" />
</mx:FormItem>
<mx:FormItem label="Last Name">
<mx:TextInput id="lastName" keyUp="keyUpHandler(event)" />
</mx:FormItem>
<mx:FormItem label="Email">
<mx:TextInput id="email" keyUp="keyUpHandler(event)" />
</mx:FormItem>
<mx:FormItem label="Account Type">
<mx:ComboBox id="accountType" dataProvider="[bronze,silver,gold,platinum]"
Trang 20Overview | 189
A picture is worth a thousand words, and with Flex you have the ability to add tures as well as animation, audio, and video Flash Player started its roots in graph-ics and animation, and over time it has grown into a strong development runtime forinteractive custom user interfaces Flash Player has a long history in handling richmedia on the Web, and Flex can leverage that strength and provide a truly engaginguser experience Flash Player not only handles many of the bitmap graphics formatstraditional web browsers do, but it also has native support for vector-based graph-ics, animation, audio, and video
pic-This chapter covers loading and embedding assets, streaming media, supportedmedia types, and working with the different media types
Overview
In an application, media can be incorporated in two ways: at runtime or at compile
time Adding media at compile time is called embedding, because the content is piled into the SWF Adding media at runtime is called loading because the content
com-exists as separate files that must be loaded into the Flex application when they arerequested
One other method of loading media is called streaming We will
dis-cuss streaming in the section “Working with Audio and Video” later
in this chapter, because streaming applies only to those media types.
There are benefits to both methods Which one you choose is important, becauseeach one can impact the loading time of your application, the file size of the result-ing SWF, the ability to change the media after an application is compiled, and theability to dynamically change content
For example, it’s beneficial to embed content within a SWF file; doing so makes themedia asset available to the application as soon as it is initialized, since it is pack-aged within the SWF file that is used to load the application It is a good idea to
Trang 21embed small assets, such as button icons and application skins that often don’t need
to be redefined at runtime You will typically want such graphics to be availableimmediately, as they can negatively impact the perceived performance of your appli-cation if each item requires a separate download
You also can embed assets using runtime shared libraries Because
runtime shared libraries are loaded when an application is initialized,
they are treated in the same manner as embedding assets within the
main application SWF We covered working with shared libraries in
Chapter 2.
It’s beneficial to load content because the content won’t be embedded as a constant(resource) within your application For example, when building an application tomanage images, you cannot embed the images within your application; instead, youneed to load the images because the content will change often as new images areadded to the image repository Also, not having to embed the content within theapplication SWF will allow your application to be downloaded quickly, and once it
is initialized, the application can load the media that is needed on demand withouthaving to reload the application SWF
Supported Media Types in Flex
As mentioned earlier, Flex’s support for media is based on the capabilities of FlashPlayer Flash Player natively supports SWF, GIF, JPEG, PNG, MP3, and FLV media
Flex 2 requires Flash Player 9 or newer Our discussion of supported
media and methods of dealing with media will assume you are
target-ing Flash Player 9 or newer Although Flex 2 requires Flash Player 9,
embedded and loaded SWF media do not have to be Flash Player 9
content.
In addition to formats supported natively by the player, with the help of the Flexcompiler, you also can handle SVG content and Flash library items within SWF files.For example, the Flash Player does not natively support SVG content, but it has thetechnical capability to render basic SVG content with the help of the Flex compiler.The Flex compiler achieves this by processing SVG files and embedding the graphicsdefinition data within a compiled SWF as native Flash bytecode This means that atruntime, the developer cannot distinguish between SVG content and native Flashvector data This allows you to embed SVG content seamlessly without needing tomanually convert SVG files to Flash Because SVG support is provided by the Flexcompiler, SVG content can not be loaded dynamically at runtime
Table 9-1 lists Flex-supported media types
Trang 22Adding Media | 191
Adding Media
As mentioned before, you can add media to an application by either loading it orembedding it In this section, we will discuss the different syntax for loading andembedding media This will serve as a good foundation for understanding the meth-ods you have available to you when adding media to a Flex application In the Flexframework, watch for component properties that accept a variable of type Class.These properties usually indicate the ability to accept a media type as a value
If you have experience with developing Flash applications, you may be
accustomed to creating classes for symbols such as images for when
you want to access them in ActionScript In Flex this is no longer
required as such classes are generated automatically for you by the
compiler.
Table 9-1 Flex-supported media types
Format Media type Compiler required Notes
SWF Graphics and animation No Flex 2 requires Flash Player 9, but it can load any
SWF content You will be limited by what type of interoperability you can have with the content based on the version of the SWF content Flash Player 9 content that uses ActionScript 3.0 is the most compatible.
SWF library item Graphics and animation Yes SWF files that contain a library of multiple
graph-ics and animation can be embedded This requires the Flex compiler, and only the refer- enced library item will be embedded within the final SWF file.
GIF Graphics No Standard GIF is supported, including
transpar-ency Animated GIF files are not supported JPEG Graphics No Baseline JPEG files as well as progressive JPEG
files are supported.
PNG Graphics No Both PNG8 and PNG24 are supported Alpha
transparency is fully supported as well.
SVG Graphics Yes The Flex compiler supports the SVG 1.1 basic
specifications SMIL, animations, filters, pattern fills, advanced gradients, interactivity, and scripting are not supported.
streamed using an RTMP server.
FLV Video No FLV is Flash’s video file format Files can be
loaded, embedded, and streamed using an RTMP server.
Trang 23Loading Media
Many of the Flex framework components are designed to enable you to easily loadmedia into your application Often this is possible with one MXML tag InternallyFlex ultimately makes use of Flash Player’sLoaderclass You typically will not makeuse of theLoaderclass directly as Flex framework abstracts away the details, but it isgood to know it exists, and if you ever need to implement loading of custom filetypes not supported by Flex, you could easily do so Here is an example that uses anImage tag to load a jpg file:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Image source="assets/sun.jpg"/>
</mx:Application>
This simple code loads an image file called sun.jpg at runtime and displays it in an
Image component The JPEG file format is native to Flash Player; as such, you areable to load it at runtime Also important to note is that the application SWF doesnot contain the image; rather, it begins loading after the application is initialized.This behavior is very similar to how web browsers load images that are referenced in
an HTML document
Loaded assets are referenced at runtime based on the location of the
swf file by default You can reference assets both using absolute and
relative paths.
This example uses theImagecomponent, which is is a Flex component built to helpyou easily load images TheImagecomponent loads the image provided by the sourceattribute and sizes it according to thewidth andheightproperties of theImagecom-ponent instance, if any are provided If no size is specified, the component expands
to the dimensions of the image Also, theImage component by default loads ever you set in the source property If you want to load the image based on userinput or an event, you can call theload( )method of theImageinstance at runtime.Here is an updated example of the preceding code that provides users with a button
what-to load the image when they want what-to view it, with no explicitwidthorheightties set:
proper-<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Image id="sun" autoLoad="false"/>
<mx:Button label="Load Image" click="sun.load('assets/sun.jpg')"/>
</mx:Application>
This version of the application does not automatically load the image, as before TheImagecomponent instance exists, but it loads the image only after the application isinitialized Also, thesourceproperty has no value in this example When you do notspecify the source property for an Image instance, the component will not load an
Trang 24Adding Media | 193
image automatically When a user clicks on the button, theload( )method is called,along with the value of the image to load as a parameter Using this method also hasother benefits
The Flash Player security sandbox applies to loading media in the
same way as loading data If you plan to load media from a server
other than the server where the application is loaded, you will need to
keep these restrictions in mind Refer back to Chapter 2 for more
information on Flash Player security.
The Flex framework is designed to simplify many common tasks, such as loadingmedia However, as already shown, the Flex framework is written in ActionScript,and as such, it leverages lower-level Flash Player APIs Although it is not necessary tolearn the Flash Player APIs in many cases, doing so almost always provides greaterinsight into how the Flex framework operates, and it enables you to create morecomplex applications When loading content using MXML tags such as Image, thecomponents are using an ActionScriptLoader object behind the scenes TheLoaderclass also exposes an instance, LoaderInfo, which allows you to gain insight on thestatus of the loaded content This can be desirable if you wish to ensure that thereare no errors attempting to load the content, or when you would like to know theprogress of the loading process TheLoaderInfoclass dispatches the following events
to indicate progress:complete,ioError,open,httpStatus, andinit These events aretypically mapped by the Flex components, so you don’t have to worry about theLoaderInfo instance as well
The Flex framework components use the underlying Flash Player API
to load media To learn the internal details about the underlying
mechanism that Flex uses to load images, review the documentation
on the Loader class in the flash.display package.
The events you’ll be most interested in are progress, complete, and ioError Theprogressevent is dispatched while an asset is being loaded This allows you to pro-vide the user with a progress bar or some other indication that something is loading.This is especially useful when loading a lot of content or large content Thecompleteevent allows you to determine when an asset has finished loading This can be useful
if you want to provide some sort of notification to the user, or have another processbegin after the content is loaded TheioErrorevent is important when having to dealwith content that may or may not exist, especially if the user is asked to enter hisown URL, for example TheioErrorevent is dispatched when Flash Player is unable
to find the referenced file, allowing you to provide the user with the option ofreentering the URL An error is usually reported immediately if the client receives aresponse from the server that shows an error such as File Not Found, but if you refer-ence a server that cannot be reached the response will not be returned in a timelymanner, if ever
Trang 25The following code allows a user to enter a URL of an image to be loaded and fies the user if he has entered an invalid URL:
Alert.show("There was an error loading: "+imageUrl.text+",
please enter a new URL");
}
]]>
</mx:Script>
<mx:Image id="imageView" ioError="ioErrorHandler( )"/>
<! when compiled and run locally, you can load remote images without security restriction that are typically encountered with an application running in the browser sandbox >
<mx:TextInput id="imageUrl" text="http://www.google.com/intl/en/images/logo.gif"/
Embedding media with MXML
The embed syntax when used in MXML begins with an @Embed( ) directive The @instructs the compiler that it will be receiving a directive—in this case, the Embed( )directive
Here is the earlier code snippet, but with the media embedded in MXML:
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml">
<mx:Image source="@Embed(source='assets/sun.jpg')"/>
</mx:Application>