Accessibility

Table of Contents

Exploring a unified component workflow between Flex and Flash

Building the Flex component

I got started on version 2 of the project: publishing a Flex component from Flash. I duplicated the project folder and got started converting the video player app. The process for creating a Flex component in Flash is actually pretty straightforward, and certainly well documented. In fact, when you download the Flex Component Kit for Flash, there is a 21-page PDF file that includes step-by-step explanations and walkthroughs.

The first step is to install the Flex Component Kit for Flash CS3 Professional, if you haven't already. You can download the kit from Adobe Labs.

The download includes an MXP file, which you can install through the Adobe Extension Manager. Launch the Adobe Extension Manager (which you should have if you already have Flash CS3 installed). Click Install and then navigate to and select the MXP you just downloaded. Click Accept on the disclaimer/agreement. When you are done, your Extension Manager window should look something like Figure 5.

Adobe Extension Manager with Flex Component Kit for Flash CS3 installed

Figure 5. Adobe Extension Manager with Flex Component Kit for Flash CS3 installed

Make sure the new Flex component is checked. If Flash CS3 is open, restart it. Now Flash CS3 is ready to start creating Flex components.

Lesson 1: Lose the document class

My first problem appeared immediately: I'd built my Flash stand-alone version using a Document class. This meant that the main class file for my video player was attached to my main Timeline. But authoring any component in Flash requires a symbol in the Flash document library, and the main Timeline is not in the library. So I created a new MovieClip symbol in my library called Player, removed the document class linkage on the FLA file (so the main Timeline no longer had a class file association), linked the new Player movie clip to the Player class, and made the appropriate changes to the Player.as file. The Player movie clip in my library was actually empty, as the Stage was in Version 1; it just linked to the Player class, which controlled and instantiated all objects as needed. Figures 6 and 7 show the structure before and after this process.

Original association between Player.as and Player.fla

Figure 6. Original association between Player.as and Player.fla

Revised association, with Player.fla linked to a new Player movie clip

Figure 7. Revised association, with Player.fla linked to a new Player movie clip

Lesson 2: Don't link the main MovieClip symbol  to a custom class

Now my second problem popped up. I successfully converted my player to run from a movie clip in the library rather than the document itself. However, this required linking the Player MovieClip to my Player.as. What's wrong with that? Well, for Flash to convert a movie clip into a Flex component, there must be a linkage ID assigned to the movie clip that will serve as the component name in Flex. When I tried linking that movie clip to a custom class file in Flash, I experienced no end of problems. In short, I couldn't figure out how to do it; I couldn't successfully have the linkage ID for the movie clip both link to a custom class and serve as the component identifier in Flex. It didn't crash or cause an error to appear—it just kept failing in new and imaginative ways.

So I created a new movie clip in my library called MediaPlayerFlexComponent. Then I inserted some code on frame 1 of the timeline of this new movie clip that instantiated and initiated the video player. Simplified somewhat for the purposes of this article, this code looked like the following:

import com.almerblank.ABMP.Player;
var player:Player = new Player();
addChild(player);

Yes, code on the timeline! Sorry. If it it makes you feel any better, what I ended up doing was taking that code, pasting it into an AS file (just an ActionScript file, not a class file) and then including that with the following line:

include "../com/almerblank/ABMP/shell/ABMP_flx.as";

In this way, I could still manage the timeline code from the project package, ABMP.

To finish this process off, I needed to establish the proper linkage for my new MediaPlayerFlexComponent. To do this, right-click the symbol in your library and select Linkage.

Ensure that Export for ActionScript and Export in First Frame are checked. Next to Class, enter the name by which you want to refer to this component in Flex (see Figure 8). In this case, I used MediaPlayerFlexComponent. I left Base Class unchanged from the default flash.display.MovieClip setting.

Setting linkage properties for the MediaPlayerFlexComponent MovieClip

Figure 8. Setting linkage properties for the MediaPlayerFlexComponent MovieClip

Now the structure of the app looked like Figure 9.

Video player app after creating and linking the MediaPlayerFlexComponent

Figure 9. Video player app after creating and linking the MediaPlayerFlexComponent

Exporting the Flex component

Now I could finally export the Flex component from Flash. To do this, select the MediaPlayerFlexComponent MovieClip in the library and then select Commands > Make Flex Component.

If your FLA frame rate is not set, the default Flex frame rate of 24 fps applies (which it wouldn't be if you left it at the default Flash frame rate of 12 fps). You will now see a dialog box prompting you to approve the change to 24 fps. If you do see this dialog box, click OK. Fortunately this will have little effect on the component because all code and object instances occur on a single frame.

The first time you compile this component, in the Flash Output panel, you should see a messaging similar to this:

Command made the following changes to the FLA:
   Turned on Permit Debugging
   Turned on Export SWC
   Set frame rate to 24
   Imported UIMovieClip component to library
Component "MediaPlayerFlexComponent" is ready to be used in Flex.

As you can see from line 5, an instance of the UIMovieClip component has been added to your FLA library. And if you check the linkage of MediaPlayerFlexComponent, you will see that the base class has been automatically updated to mx.flash.UIMovieClip (see Figure 10).

For more information on the UIMovieClip, check the UIMovieClip entry in the Flex 3 Language Reference.

Updated linkage properties for MediaPlayerFlexComponent

Figure 10. Updated linkage properties for MediaPlayerFlexComponent

From now on, when you want to update this component, all you have to do is generate the SWF file by selecting File > Publish or Control > Test Movie.

In whatever folder you have set as the destination for your published SWF file, you will now see a SWC file of the same name as the SWF file. That SWC file is your Flex component.

Ready to test in Flex

To start testing this component, open up Flex Builder and create a new project. Now add your new SWC file to the project library paths. Select Project > Properties. In the left column, select Flex Build Path. In the right panel, select the Library path tab (see Figure 11).

Adding your SWC file to the project library paths

Figure 11. Adding your SWC file to the project library paths

On this panel, click Add SWC, click Browse to navigate to the SWC file you just created, and then click OK. Once you do, your library paths should be updated. Click OK.

Hint: When testing this component, I was constantly updating the SWC file from Flash. Each time you update the SWC component, you need to update the SWC file that your Flex project library paths point to. I discovered that Flex will update the SWC file if you return to your library paths, select the SWC component, click Edit, click OK without changing anything, and then click OK once more to update the library paths. You don't have to remove and re-add the SWC file each time.

In your application MXML, you must specify the namespace your new SWC component uses. The default (which is what your SWC uses unless you override it) is global, or *. So, in the Application tag, add something like:

      xmlns:myswc="*"

Now, when you start a tag like this:

      <myswc:

you should see some code hinting from Flex Builder indicating that it knows your new component (see Figure 12).

Flex Builder hinting based on your namespace

Figure 12. Flex Builder hinting based on your namespace

That's great. It works! Or, if your component looks a bit more like mine did at this stage, it doesn't. Which brings me to the next set of challenges.

Lesson 3: Let's get physical

In order for Flex to handle your component properly, there must be something physical on the timeline of the movie clip from which the SWC is generated. As I explained, in this version I instantiated everything from the Player class, so there was nothing on the timeline. Which meant it didn't work.

Of all the challenges that popped up, this was the most easily surmountable. I returned to Flash, edited the MediaPlayerFlexComponent MovieClip, drew a rectangle on the Stage, and gave it a fill with 0% alpha (so it was effectively invisible). I then republished my app (updating the SWC file), updated the library paths in my Flex project, and retested.

Voilà, it worked! Figure 13 shows the app structure after learning that lesson.

Video player structure after adding a graphic to the Stage

Figure 13. Video player structure after adding a graphic to the Stage

Lesson 4: Scale control

One feature of this video player is the ability to render dynamically for different sizes. The player, which is designed at about 400 × 400 (I'm using round numbers instead of the actual dimensions, for simplified math), doesn't simply scale, it makes more intelligent choices on how to accommodate runtime dimensions that are different than those of the initial design. For example, the control bar is always 24 pixels tall, no matter how tall the player is.

In order to test this feature in Flex, I modified the width and height values of the MXML tag:

<myswc:MediaPlayerFlexComponent id="MyVideoPlayer"
    width="200" height="200"/>

When I tested the component with these settings, I discovered an odd behavior of altering the widths and heights of these components. Instead of rendering at 200 × 200 pixels with the proper layout adjustments I'd accounted for in the code, the player rendered at 100 × 100 pixels—and just scaled down, with none of the layout indications my code should have handled.

It took me a little bit of playing around to figure out what was going on. When instantiating your component, Flex compares the original size of your component (the width and height of the graphic we placed on the Stage, which in our case is 400 × 400) to the size of the instantiated component (here, 200 × 200) and concludes that the scaleX and scaleY are 50% (200 / 400). So Flex renders the component instance at 200 × 200 but also applies a scale transformation, so the component instance actually appears at 100 × 100 (50% of 200 × 200).

In the end, all I did to remedy this situation was apply these two lines of code to my ABMP_flx.as ActionScript file, which is included on frame 1 of the MediaPlayerFlexComponent MovieClip inside of Flash:

scaleX = 1;
scaleY = 1;

This forces the component instance to render at 100% of its scale. Voilà! It all worked. At this point, my video player looked something more like Figure 14.

Video player now adjusted for scale

Figure 14. Video player now adjusted for scale

Moving on

So now I had two separate, but very similar, code bases to produce the same application in two different ways—as a Flash SWF file and as a Flex component. As my next step, I wanted to get the code to work to produce a FLA-editable Flash component.