четверг, 21 апреля 2011 г.

Creating and applying custom preloader to Flex application (part 1)

I'm sure, you can find much information on this issue on the internet, but i'll try to explain the process in a detailed way, that it'll be easy to understand. I'm going to show you 2 ways of creating and applying your custom preloader for Flex application.

First of all, let's refer to Preloader class. Before displaying application to user SystemManager creates Preloader instance, which is responsible for monitoring application loading progress and loading RSLs. But Preloader is not something you see before your application loads.

The Preloader class instantiates a download progress bar, which must implement the IPreloaderDisplay interface, and passes download and initialization events to the download progress bar. 

So, IPreloaderDisplay is exactly what we see, while application is loading. This means, that we are going to write class implementing IPreloaderDisplay interface. Let's take a look at its properties and methods signatures.

function get backgroundAlpha() : Number;
function set backgroundAlpha(value : Number) : void;
function get backgroundColor() : uint;
function set backgroundColor(value : uint) : void;
function get backgroundImage() : Object;
function set backgroundImage(value : Object) : void;
function get backgroundSize() : String;
function set backgroundSize(value : String) : void;
function set preloader(obj : Sprite) : void;
function get stageHeight() : Number;
function set stageHeight(value : Number) : void;
function get stageWidth() : Number;
function set stageWidth(value : Number) : void;
function initialize() : void;


We're going to create animated MovieClip as IPreloaderDisplay, that's why we're not interested in   backgroundAlpha, backgroundColor, backgroundImage and backgroundSize. We will return to implementing other methods later, and now let's create simple progress bar in Flash IDE.

If you're not newbie in Flash IDE, you may skip these steps.

1. Create new MovieClip. Give it any name you want.
2. Go to it's properties and check "Export for ActionScript". Set class name (i named it "PreloaderBar").




3. Create 3 layers (for progress label, for mask, for progress bar).
4. On progress bar layer create simple rectangle shape .
5. On label layer create TextField, put it anywhere near progressbar and give it a name (i named it "label").
6. On mask layer create rectangle shape (it's width and height should be bigger than progressbar's one).
7. Put it to the left from progressbar (they should be almost in touch).




8. Create 100th keyframe. Select it and put mask rectangle on progressbar (should overlay).
9. Create classic tween from 1st to 100th frame on mask layer.
10. Make mask layer Mask :)




11. Right click on our movieclip in library -> Export SWC file...

Now we need to add exported SWC to our project as a library. So, we have movieclip for our prelader. Let's extend it and implement  IPreloaderDisplay  interface. Setter preloader passes Preloader instance to our class so that we could listen to it's events. We're interested in two events of Preloader - ProgressEvent.PROGRESS and FlexEvent.INIT_COMPLETE.


public function set preloader(preloader : Sprite) : void
{
      _preloaderView = preloader;
      _preloaderView.addEventListener(ProgressEvent.PROGRESS, onProgress);
      _preloaderView.addEventListener(FlexEvent.INIT_COMPLETE, onComplete);
}
 
private function onProgress(event : ProgressEvent) : void
{
      var progressPercent : int = event.bytesLoaded / event.bytesTotal * 100;
      label.text = progressPercent.toString() + "%";
      gotoAndStop(progressPercent);
}
 
private function onComplete(event : FlexEvent) : void
{
      dispatchEvent(new Event(Event.COMPLETE));
}


On PROGRESS event we update label text displaying percent progress of loading and we set our movieclip to corresponding frame.
On COMPLETE event it's necessary to dispatch  COMPLETE event. Preloader is listening to it, and it will tell SystemManager to hide preloader and to show application.
Initialize() method is a good place to configure our preloader view.

public function initialize() : void
{
      stop();
      centerPreloader();
}


What concerns other methods implementation, we'll make default set-get realization. Here's full listing of our class:

package
{
 import flash.display.Sprite;
 import flash.events.Event;
 import flash.events.ProgressEvent;
 import mx.events.FlexEvent;
 import mx.preloaders.IPreloaderDisplay;
 
 public class MyPreloader extends PreloaderBar implements IPreloaderDisplay
    {
        private var _backgroundAlpha : Number;
        private var _backgroundColor : uint;
        private var _backgroundImage : Object;
        private var _backgroundSize : String;
        private var _stageHeight : Number;
        private var _stageWidth : Number;
        private var _preloaderView : Sprite;
 
        public function MyPreloader()
        {
            super();
        }
 
        public function set preloader(preloader : Sprite) : void
        {
            _preloaderView = preloader;
            _preloaderView.addEventListener(ProgressEvent.PROGRESS, onProgress);
            _preloaderView.addEventListener(FlexEvent.INIT_COMPLETE, onComplete);
        }
 
        private function centerPreloader() : void
        {
            x = (stageWidth / 2) - (width / 2);
            y = (stageHeight / 2) - (height / 2);
        }
 
        private function onProgress(event : ProgressEvent) : void
        {
            var progressPercent : int = event.bytesLoaded / event.bytesTotal * 100;
            label.text = progressPercent.toString() + "%";
            gotoAndStop(progressPercent);
        }
 
        private function onComplete(event : FlexEvent) : void
        {
            dispatchEvent(new Event(Event.COMPLETE));
        }
 
        public function get backgroundAlpha() : Number
        {
            return _backgroundAlpha;
        }
 
        public function set backgroundAlpha(value : Number) : void
        {
            _backgroundAlpha = value;
        }
 
        public function get backgroundColor() : uint
        {
            return _backgroundColor;
        }
 
        public function set backgroundColor(value : uint) : void
        {
            _backgroundColor = value;
        }
 
        public function get backgroundImage() : Object
        {
            return _backgroundImage;
        }
 
        public function set backgroundImage(value : Object) : void
        {
            _backgroundImage = value;
        }
 
        public function get backgroundSize() : String
        {
            return _backgroundSize;
        }
 
        public function set backgroundSize(value : String) : void
        {
            _backgroundSize = value;
        }
 
        public function get stageHeight() : Number
        {
            return _stageHeight;
        }
 
        public function set stageHeight(value : Number) : void
        {
            _stageHeight = value
        }
 
        public function get stageWidth() : Number
        {
            return _stageWidth;
        }
 
        public function set stageWidth(value : Number) : void
        {
            _stageWidth = value;
        }
 
        public function initialize() : void
        {
            stop();
            centerPreloader();
        }
    }
}
 


What's left? Right, we need to set our Application's property preloader to our class name.
<?xml version="1.0"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
      xmlns:s="library://ns.adobe.com/flex/spark"
      preloader="MyPreloader">
 <fx:Script><![CDATA[
  [Embed(source="embed_me.mp3")]
  private var music : Class;
  ]]></fx:Script>
 <s:Label fontSize="20" text="Application loaded"/>
</s:Application>

I've embedded 1mb mp3 file to make swf file load not so fast.
In next post i'll tell you about another way of attaching custom preloader to Flex application.


Run example
Download sources

Комментариев нет:

Отправить комментарий