Making a Cooler Preloader in Flex: Part 1 of 3

Preloader Preview

Preface

Preloaders in Flex are not like preloaders in Flash. Gone are the days of the 1 liner:

if ( _framesloaded < _totalframes ) gotoAndPlay ( 1 );

We now have base classes and setter properties. While you may have to write a class and then set that class on your Application’s preloader property, it’s really pretty easy once you do it more than once. This tutorial will show you how to build a preloader in Flex using a Flash built animation.

Introduction

Flex’ built in preloader is pretty sweet. It auto-adjusts for your application’s color to stand out, it handles all aspects of preloading. This includes remote shared libraries, fonts, and even deferred classes used in modules. Finally, it deals with the initialization of your Flex application which can possibly take longer than a few milliseconds.

If you are building branded applications, every little detail counts in enforcing your brand identity upon your user. You want to remind them the positive experience they are having was brought to them by you. Nothing is more important than a first impression, and the first thing people see in a Flex application is the preloader. It is important that you spend adequate time on making it look good and consistent.

To make a custom preloader for Flex, you have to do 2 steps:

  1. Write a class that extends DownloadProgressBar
  2. Set the preloader property on your Application class to your preloader class.

No witty 3 step process here.

The purpose of extending DownloadProgressBar is to handle the various things that happen in the life cycle of preloading (yes, we have life cycles now, not just downloading of bits). You do not have to handle anything save the FlexEvent.INIT_COMPLETE. You could for example put some dots who are ridin’ spinnaz and that’s your preloader.

…or, you could handle all events, and duplicate the Flex one with a different design showing the download & initialization progress.

The steps for making a custom Flash Preloader for your Flex app are as follows:

  1. Make a 100 frame MovieClip. TextField optional (as is everything).
  2. Give MovieClip linkage ID with no class name.
  3. Compile your SWF (“Test Movie”)
  4. Write your own Preloader class in Flex Builder which uses your Flash MovieClip.
  5. Set the Appliction.mxml preloader property to your custom class.

Making Your Flash Symbol

In Flash, you make a MovieClip that is 100 frames long. This will be the preloading part of your preloader, the MovieClip that shows the progress of the SWF downloading. Notice I have both a 100 frame animation as well as a dynamic TextField. The TextField will have the percentage numbers (i.e. “73%”) put into it dynamically.

Notice, also that the TextField has an instance name. This is so I can target it with code. Keep in mind, even though we are giving the TextField an instance name, we’ll be targeting it with code in Flex. We won’t be writing any code in Flash.

Finally, I wrap my preloader in a MovieClip because I want the preloader to fade out when it’s done.

I make sure to give the preloader an instance name so I can “dot dot down” to the preloader through the animation. Dot dot down is Flash slang for using dot syntax to walk down the display tree to target a MovieClip you want to interact with via code. In our case, it could be:

_root.my_clip.preloader.amount_txt.text = "70%";

Omg, I used _root, lol, l@mz03, me fired.

Finally, you export your Symbol with a linkage ID. Exporting as Flash 8, AS2, you just fill in the linkage ID class. Don’t export as Flash 9, AS3. If we did that, we might as well write the class for the preloader , and that’s just too much work, and too much added file-size for a class that’s supposed to be simple and most of all lightweight. If you are using Flash CS3, just change your publish settings to Flash 8, AS2 or AS1.

Flex will look for this linkage ID name when you are embedding the MovieClip. Now compile your SWF and your done.

Custom Preloader Class

You then write your own Preloader class. Have it extend mx.preloaders.DownloadProgressBar. There are multiple ways to embed Flash content. For our purposes, we’ll embed to a class property.

If you look at the Preloader’s setter function, you’ll see we get a Sprite (1 frame MovieClip) that emits all the preloading events we’ll care about. In this case download progress, when the SWF has finished downloading, when the SWF starts to initialize classes, and when initialization is complete.

Our download progress & SWF download done functions will dig down into the Flash MovieClip, and show download progress in both the text field, as well as making the preload MovieClip symbol animate via gotoAndStop based on the download percentage. Since download percentages are 100%, it makes it pretty easy to figure out what frame to go to.

The initialization ones just show “Initializing…” in the TextField.

Unlike most Flex preloaders, we want ours to animate when done, and only THEN actually launch into our Flex application. You can accomplish this by not dispatching the complete event. Dispatching this let’s the Flex application know the preloader is done. In our case, we want to wait till the Flash animation is done before doing so. We add a framescript ( a function called when the Playhead reaches a frame) to frame 21. When the animation is done, it’ll hit this frame, call our preloader class’ function. This will stop the animation and dispatch the event, letting the Flex application know we’re ready.

Conclusion

That’s it! Keep in mind it’s hard to test these things locally on your box. In Flash, we have the bandwidth profiler, but there is no such thing in Flex. You can either use network throttlers, like Charles. Alternatively you can upload the files to your site, install the Firefox Web Developer Toolbar, and choose disable cache.

In the next part, we’ll be taking advantage of Flex as a statefull client, and getting all the data you need. This takes time, so we need a cool way to show this to user as well as making it fail gracefully.

Flash Preloader in FlexExample | Source | ZIP

61 Replies to “Making a Cooler Preloader in Flex: Part 1 of 3”

  1. Jesse, man, you don’t have to make tutorials just for me. Seriously. I mean, I know I need schoolin’ from time to time, but let’s not make it personal! ;-)

    Thanks for this tutorial. As always, I think you’ll make as great a father as you will a developer!

  2. Awesome stuff! There are caveats you may want to consider. I fixed them when using your example.

    1. Your preloader overwrites the event Listeners, but you leave them once your application is loaded. This is ok if you never load anything else into your flex application. When loading a module into your application, flex will fire the FlexEvent.INIT_PROGRESS event again causing an error due to the clip.preloader becoming null.

    2. Solution:
    Instantiate a private variable called _preloader in your constructor;

    private var _preloader:Sprite;
    
    public override function set preloader(preloader:Sprite):void
    {
            _preloader = preloader;
            _preloader.addEventListener( ProgressEvent.PROGRESS , onSWFDownloadProgress );
            _preloader.addEventListener( Event.COMPLETE , onSWFDownloadComplete );
            _preloader.addEventListener( FlexEvent.INIT_PROGRESS , onFlexInitProgress );
            _preloader.addEventListener( FlexEvent.INIT_COMPLETE , onFlexInitComplete );
            centerPreloader();
    }
    
    

    Remove the listeners once the application is loaded and you are complete;

    private function onDoneAnimating():void
    {
            clip.stop();
            _preloader.removeEventListener( ProgressEvent.PROGRESS , onSWFDownloadProgress );
            _preloader.removeEventListener( Event.COMPLETE , onSWFDownloadComplete };
            _preloader.removeEventListener( FlexEvent.INIT_PROGRESS , onFlexInitProgress );
            _preloader.removeEventListener( FlexEvent.INIT_COMPLETE , onFlexInitComplete );
            dispatchEvent( new Event( Event.COMPLETE ) );
    }
    

    Regards,
    Tony

  3. Thanks,It was helpful for me.But I wanna create custom context menu.Can u post me some of examples or some hint.

  4. Hello Jesse, thanks for the posting. But I have hard time to reference to the text box as in the code
    clip.preloader.amount_txt.text = “Initializing” , I keep getting error on property preload not found.
    I surely give it a instance name for the movie clip in flash 8.

    Is this the problem that I have to use CS3 and save backward compatible as AS2? Thanks ahead.

    Mark

  5. hey i tried doing the tutorial but i get an error when my preloader comes in. this is what i have:

    ReferenceError: Error #1069: Property preloader not found on Preloader_FlashPreloaderSymbol and there is no default value.
    at Preloader/::onSWFDownloadProgress()
    at flash.events::EventDispatcher/flash.events:EventDispatcher::dispatchEventFunction()
    at flash.events::EventDispatcher/dispatchEvent()
    at mx.preloaders::Preloader/::timerHandler()
    at flash.utils::Timer/flash.utils:Timer::_timerDispatch()
    at flash.utils::Timer/flash.utils:Timer::tick()

    anyone have a clue?

  6. I think that’s because the flex can not reference to the object name inside of flash. Need the Guru to clear the way.

  7. Hello, I am getting the same problem as mizzle. Would you mind posting the sources for your flash preloader so that we can have a easier time modifying it for our needs? Thanks so much!

  8. Thanks for this great tutorial, i was waiting for it for a long time!
    but i have the same error 1069 than the others above…
    Maybe you could provide us a example .fla for help?

  9. Actually i resolved it!
    you have probably sets your 2 layers (with flags and fade out) directly on the stage. Try to wrapped them in a movie clip. It worked for me, the scene is empty and in my library i have a movie clip (named PreloaderAnim) and another movie clip (Preloader, used in PreloaderAnim) which is linked.

    Hope that’s help and sorry for my english if i made mistakes!

  10. I am confused about movie clip structure.
    How many movie clips are used 1 or 2? (For Loader and wrapper)
    Please give Source flash file for above mentioned tutorial.

  11. Hey Jesse,

    Really loved the tutorial… could you post the .fla file? i think there are a lot of people trying to build on this example, and when they try and build something custom in flash, they aren’t wrapping it the same way you did…

    i think the .fla would clear everyone up…

    it would for me anyway…

    thanks you

    Axel

  12. Sorry for the delay peeps. I cannot give the FLA since I don’t own the graphics, so I made a new one. This one, built like I describe above, works as well. I downloaded the source, saved the FLA in assets/flash, recompiled the preloader.swf to use the new one from this FLA, and she works on my Flex 2.0.1, Windows XP, Eclipse 3.1, Java 1.5. FLA is saved as Flash 8 (built in Flash CS3, but saved in case yall don’t have CS3), exports Flash Player 8, ActionScript 2.

    Any probs, let me know.

    Download Preloader FLA

  13. Hey Jesse,

    Have you tried the preloader in FLEX 3 Beta 2? I am getting an error when I try to use it in an AIR application and working through it right now. Was hoping you might shed some light on how to get it working with AIR.

    Thanks,
    Tony

  14. I do now know how build the .fla in flash

    I use flash 8 professioal,and as this tutorials, and also JesterXL says on “September 30th,2007 at 10:49 pm”,I download the “Preloader FLA”, use the FLA, I republish it in flash 8 professional, then copy the .swf to my flex project directory,and use the Preloader.as In my project, It works very well;
    So it proves my environment is OK;

    Then as this tutorials, and as your .fla does, I make a new .fla in my flash 8 professional ,publish it ,copy .swf to my flex procect, then In Preloader.as ,change the “[Embed source=”/assets/flash/preloader.swf”, symbol=”PreLoader”)]” to “[Embed source=”/assets/flash/preloader.swf”, symbol=”MyPreLoader1″)]”,and recompile my flex project, it is OK, but when I run the flex project, get the wrong message as follows:

    TypeError: Error #1034: Type Coercion failed: cannot convert Preloader_FlashPreloaderSymbol@435fcf1 to flash.display.MovieClip.
    at Preloader$iinit()
    at mx.preloaders::Preloader/initialize()
    at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::initialize()
    at mx.managers::SystemManager/::initHandler()

    Why it is Ok using your .fla, but it does not work using my own .fla??
    But In flash 8 professioanl, I make it the same as your .fla as fowllows:
    1. make a new flash project, named as preloader.fla;
    2. In this flash project, make a new Movie Clip symbol, and only one frame, put a dynamic text in it , then set the Movie Clip Linkage to “MyPreLoader1”, set the Publish setting: Flash Player 8, Actionscript 2.

    Why it does not work using my .fla??
    Then I want to know what is the Tips on making a new flash??

  15. Now I found the problem.

    If the symbol only have one frame, It will not work as I had said.

    But I now find a new problem.

    The amount_txt does not show the progress number when progressing,only show 99% at last.
    It can not show the pregressing number 1~98% when progressing.

    Why?? I think the problem is not that the swf file will be loaded is very small.
    To debug this problem , I change some at the function onSWFDownloadProgress as follow:

    if(p

  16. Now I found the problem, but a new problem.

    If the symbol only have one frame, It will not work as I had said.

    But I now find a new problem.

    The amount_txt does not show the progress number when progressing,only show 99% at last.
    It can not show the pregressing number 1~98% when progressing.

    Why?? I think the problem is not that the swf file will be loaded is very small.
    To debug this problem , I change some at the function onSWFDownloadProgress as follow:

    if(p

  17. Now I found the problem, but a new new problem.

    If the symbol only have one frame, It will not work as I had said.

    But I now find a new problem.

    The amount_txt does not show the progress number when progressing,only show 99% at last.
    It can not show the pregressing number 1~98% when progressing.

    Why?? I think the problem is not that the swf file will be loaded is very small.
    To debug this problem , I change some at the function onSWFDownloadProgress as follow:

    if(p

  18. Now I found the problem.

    If the symbol only have one frame, It will not work as I had said.

    But I now find a new problem.

    The amount_txt does not show the progress number when progressing,only show 99% at last.
    It can not show the pregressing number 1~98% when progressing.

    Why?? I think the problem is not that the swf file will be loaded is very small.
    To debug this problem , I change some at the function onSWFDownloadProgress as follow:

    [code]
    if (p

  19. At last, I would say the amount_txt does not show the incresing number from 1~99%, it only at last show 99%.

    Why??

  20. Hey mill88, figured your first problem out (I hope). If an embedded symbol has 1 frame, it is considered a Sprite and cannot be cast to a MovieClip. If it has more than one frame, it appears to be considered a MovieClip.

  21. How to use in flex builder 2, but occur a error

    It´s necessary using AS3

    on

    [Embed(source=”/assets/flash/preloader.swf”, symbol=”Preloader”)]

  22. Hi Jesse, I had an error as described above. I renamed my symbol from Preloader to Preloader2, I think the class name being Preloader doesnt like the symbol being the same or something. Anyhow, that error went but then a new ‘Type’ error arrived when trying to convert clip to FlashPreloaderSymbol as in line 35 – clip = new FlashPreloaderSymbol(); – anyone else get this. Very frustrating having to abandon this. Tried casting to no avail. word..

  23. Hey,

    nice tutorial! I need to play an Animation, before the actual download progress bar is displayed. When the application is loaded from the cache, the download progress is done instantly. But the intialize phase of my application is so heavy, that the Animation is not played smoothly. What can I do? Can I delay the start of the initalize phase from the preloader?

  24. @mc davidson & Benoit
    If you replace “private var clip:MovieClip;” by “private var clip” in the class Preloader.as you can use a swf exported from CS3.
    Hope this could help

  25. Hi and thanks for great information! Has anyone got a preloader.fla that can be used in CS3?

    Hope someone can help.

    Thanks

  26. Just so you’ll know – your link to “dots” now goes to adult related search site… probably should get updated… :D

  27. Hi
    i’ve tried this preloader with an air applcation but i got this error:
    TypeError: Error #1009: Cannot access a property or method of a null object reference
    has someone solved this problem?
    thanks
    Paolo

  28. Very thanks for your helpfully tutorial, that’s save me so much time.

    十分感谢

Comments are closed.