Flex Custom Preloader

I was getting a little tired of the aqua loading screen that appears by default in all of my Flex applications, so I took a stab at building a custom preloader. A Flex application is really a two frame Flash movie, with the first frame containing all of the initialization and the second the application itself. The preloader is part of the initialization frame and we can use it to create a custom loading screen for our application. I found a few articles on the topic, with the most promising being this one from Ted on Flex.

I wanted my custom preloader to contain two elements: (1) a graphical logo and (2) a progress bar. Ted’s article provides information on loading the graphic (a PNG) by utilizing a subclass of flash.display.Loader. Because our preloader will perform its actions during the initialization frame, those handy graphical Flex classes (e.g. Image, ProgressBar) will not be available to us. Instead, we will need to create these items on our own.

If you would like to follow along, I have posted my complete source code. Please note that I embedded an MP3 in the application purely to increase its download size. I would recommend that you include a 2-3MB MP3 in your application, otherwise, the progress will not be noticeable.

To get started, we will extend the mx.preloaders.DownloadProgressBar class as suggested by Ted. As explained in the Flex documentation, the DownloadProgressBar can be extended to provide user feedback on the download and initialization phases of our Flex application. Also of note is that we need to implement it as an ActionScript class and not in MXML as the latter loads to slowly at runtime.

The CustomPreloader class is very much like Ted’s sample code, the exception being that as the SWF is loaded, we calculate the percent complete and update the progress value in our custom loading screen (LoadScreen):

    private function SWFDownloadProgress(event : ProgressEvent) : void
    {
        var prog : Number = event.bytesLoaded / event.bytesTotal * 100;
        if (this.loader)
            this.loader.progress = prog;
     }

On initialization of the CustomPreloader, we also utilize a Timer to ensure the stage is available before we try to add and position the load screen:

    override public function initialize() : void
    {
        super.initialize();

        this.loader = new LoadScreen();
        this.addChild(this.loader);

        this._timer = new Timer(1);
        this._timer.addEventListener(TimerEvent.TIMER, handleTimerTick);
        this._timer.start();
    }

From here, we extend flash.display.Loader to provide the utility for loading our logo image and drawing the progress bar. We do this by drawing both the logo and the progress bar on screen by creating a BitMap and then using the PNGEncoder to write the image to the screen as a PNG image. We are actually creating an animation on the fly here:

    public function refresh() : void
    {
        this._logoData = this.draw();
        var encoder : PNGEncoder = new PNGEncoder();
        var bytes   : ByteArray  = encoder.encode(this._logoData);
        this.loadBytes(bytes);
    }

    private function draw() : BitmapData
    {
        // create bitmap data to create the data
        var data : BitmapData = new BitmapData(this.width, this.height, true, 0);

        // draw the progress bar
        var s : Sprite = new Sprite();
        var g : Graphics = s.graphics;

        // draw the bar background
        g.beginFill(_BarBackground);
        g.lineStyle(2, _BarOuterBorder, 1, true);
        var barX : int = (this.width - _BarWidth) / 2;
        var barY : int = _TopMargin + _LogoHeight + _Padding;
        g.drawRoundRect(barX, barY, _BarWidth, _BarHeight, 2);
        var containerWidth : Number = _BarWidth - 4;
        var progWidth : Number = containerWidth * this.progress / 100;
        g.beginFill(_BarColor);
        g.lineStyle(1, _BarInnerColor, 1, true);
        g.drawRect(barX + 1, barY + 1, progWidth, _BarHeight - 3);
        data.draw(s);

        // draw the logo
        data.draw(this._logo.bitmapData, null, null, null, null, true);
        return data;
    }

To bring everything together, we are utilizing a Timer instance in our CustomPreloader class to update and redraw the progress bar on each timer tick. This calls the refresh() method in LoadScreen, which then redraws the an updated progress image. Now, we just need to add the following to our as an attirbute of the Application tag in our application MXML file to utilize the our custom preloader:

  preloader="iamjosh.samples.preloader.CustomPreloader"

Finally, let’s change the background color of the application to match our logo a little better. Just add the following Flex compiler argument:

  -default-background-color #FFFFFF

References

Update: I just found an article that accomplishes a similar task to my own buried in the comments of one of Ted’s articles. I was a little happier with how he handled the graphics of drawing the progress bar, so I have updated my code and added the article as a reference.

About these ads

12 Comments on “Flex Custom Preloader”

  1. […] incluindo as cores, logo e até um ProgressBar diferente. Você pode ver exemplos disso aqui, aqui e […]

  2. jmbara says:

    Thanks for sharing the source for your Custom pre-loader. I used it with a sound-art-toy called PlayWithMozart, which preloads several files including a large soundfont file, and the preloader works very well. I made a small change in LoadScreen’s draw() function when I observed that the “logo” image only needs to be loaded once. Both “data.draw( this._logo.bitmapData, ….)” and the code drawing the bar background can be put inside the “if( isDataNull){…}” initialization block. This change speeds up the loading process a bit.

  3. Rahul says:

    Thanks for sharing the knowledge, but please note this example does not work with Flex Builder 2.
    No PNGEncoder class

  4. Thorsten Schmitz says:

    Yeah, thank you a lot for sharing this!

    I was searching for a Preloader like this. Great work!

  5. uday says:

    if i want embed random images to pre loader, is it possible to emed those random images

  6. Gustavo Scanferla says:

    Thanks, this is a rela prealoader!

  7. Gustavo Scanferla says:

    oops: I meant “real preloader”.

  8. Alex C says:

    Awesome preloader, Josh!! Got it working in no time! One question: Any way to embed text in the preloader, such as “This application brought to you by Such and Such”?

  9. beto angeles says:

    Yessssss Josh, 1000 thanks to you, have a nice new year !!!

  10. pythagoras1 says:

    FYI, I tried to implement this solution in a live project, and the logo image flickers/blinks in IE7. Could not find a workaround. Seems unnecessary to redraw the image every time it refreshes (like you need to with the pregress bar, went with this:

    http://www.pixelbox.net/2008/03/13/changing-the-default-loading-screen-in-flex/

    and it worked better in IE7 (unfortunately that’s the browser my clients use in their offices)

Follow

Get every new post delivered to your Inbox.

Join 25 other followers