Leave That Thing Alone Blog

Flex 4 Custom Preloader

In this example were going to look at a way to create a custom preloader SWC in Flash Professional and use it inside of a Flex 4 application by extending the SparkDownloadProgressBar class.
This preloader will display the progress percentage of loading and also a count of RSLs as they are being loaded, after loading is complete the progress of initialization will be displayed. Both of the progresses will be displayed by a graphical progress bas and in text.

View Demo Preloader App (right click for source view)

The preloader may fly by, so lets first take a look at how this progress bar looks as it is loading the Flex app:
flex 4 preloader

The next screenshot shows the progress as RSLs are being loaded:
flex 4 preloader

Finally the progress of initialization, with a second progress bar:
flex 4 preloader

Creating the Preloader SWC in Flash Pro

In Flash professional we create a custom preloader. In this example there are several layers which the design is created from. The layer 'prog_bar' and 'initilize_bar" hold shapes that we will use to resize to show progress. The 'loading text' layer contains some dynamic text that has Character Embedding for upper/lower/numbers. The layers look like this:

flex 4 preloader

The custom preloader FLA can be found in the example by viewing source.

The FLA preloader is a movie clip and its properties are set for "Export for ActioScript" the "Class" property is set to "PreloaderDisplay" this allows us to have a PreloaderDisplay.swc created when this FLA is published.

flex 4 preloader

In the first frame of the FLA "actions" layer we create the functions to set the two different progress bars:

//reset
setMainProgress(0);
setInitalizeProgress(0);
loading_txt.text = "";

//function for setting main prgress bar function setMainProgress(percent:Number):void { prog_bar.width = percent * 275; }

//function for setting the initilize bar function setInitalizeProgress(percent:Number):void { initialize_bar.width = percent * 275; }

The final step is to "Publish" the FLA so that the SWC file is create, this SWC will be used in Flash Builder.

Creating the Custom Preloader in Flex 4

The first step is to place the PreloaderDisplay.swc in the "libs" folder, this will make the PreloaderDisplay and its methods available to Flex:

preloader swc libs

To define a custom preloader we will do this in the Flex application's Application file, we simply specify the preloader class:

<s:Application preloader="com.themorphicgroup.preload.Preloader" ...

In the Preloader class we will extend "SparkDownloadProgressBar". The SparkDownloadProgressBar class displays download progress.
From Flex 4 docs: It is used by the Preloader control to provide user feedback while the application is downloading and loading. The download progress bar displays information about two different phases of the application: the download phase and the initialization phase.

The Preloader.as extends "SparkDownloadProgressBar" and we will use the FLA PreloaderDisplay.swc by creating a variable called "preloaderDisplay":

public class Preloader extends SparkDownloadProgressBar {
	private var preloaderDisplay:PreloaderDisplay;
	...

To add the PreloaderDisplay we will override the SparkDownloadProgressBar's "createChildren" method, in this method we will create a new PreloaderDisplay and use the "addChild" method (SparkDownloadProgressBar inherits addChild from DisplayObjectContainer):

override protected function createChildren():void
{
	if (!preloaderDisplay) {
		preloaderDisplay = new PreloaderDisplay();
		
		var startX:Number = Math.round((stageWidth - preloaderDisplay.width) / 2);
		var startY:Number = Math.round((stageHeight - preloaderDisplay.height) / 2);
		
		preloaderDisplay.x = startX;
		preloaderDisplay.y = startY;
		addChild(preloaderDisplay);
	}
}

There are several methods that will override so that we can make updates to the PreloaderDisplay.swc. The rslProgressHandler method will be called each time a RSL is being loaded. We will use this method to set text indicating the current count of RSL being loaded:

private var rslBaseText:String = "loading: ";
override protected function rslProgressHandler(evt:RSLEvent):void {
	if (evt.rslIndex && evt.rslTotal) {
		//create text to track the RSLs being loaded
		rslBaseText = "loading RSL " + evt.rslIndex + " of " + evt.rslTotal + ": ";
	}
}

The next method we will override is setDownloadProgress. This method indicates the current download progress. in this method we will set the PreloaderDisplay.swc main progress bar and set the text:

override protected function setDownloadProgress(completed:Number, total:Number):void {
	if (preloaderDisplay) {
		//set the main progress bar inside PreloaderDisplay
		preloaderDisplay.setMainProgress(completed/total);
		//set percetage text to display, if loading RSL the rslBaseText will indicate the number
		setPreloaderLoadingText(rslBaseText + Math.round((completed/total)*100).toString() + "%");
	}
}

Finally we will look at overriding setInitProgress, this method indicates the progress of the Flex app as it initializes. We will set the text in PreloaderDisplay.swc and change the progress of the second initialize progress bar:

override protected function setInitProgress(completed:Number, total:Number):void {
	if (preloaderDisplay) {
		//set the initialization progress bar inside PreloaderDisplay
		preloaderDisplay.setInitalizeProgress(completed/total);
		//set loading text
		if (completed > total) {
			setPreloaderLoadingText("almost done");
		} else {
			setPreloaderLoadingText("initializing " + completed + " of " + total);
		}
	}
}

 

This blog entry does not cover every bit of code used in the preloader, so View Demo Preloader App right click for source view

 

Comments

julien's Gravatar nice example, thanks for sharing
# Posted By julien | 11/11/09 12:09 PM
Mukul's Gravatar Hi, I've been trying to follow this for the past couple hours, and not making much progress. I was wondering if this needs to be done with Flash CS4 or would Flash CS3 also be adequate.

I generally get a null pointer exception when I try to access the loading_txt.text, and I've got it to not give me a null pointer, but then nothing is ever shown on the screen during the loading. The null error also occurs when I try to call either of the set functions. Please let me know if there's a solution to this. Thanks.
# Posted By Mukul | 1/23/10 12:22 AM
Seth's Gravatar Doesn't matter if you use CS3 or CS4 just make sure when you create the SWC that the FLA properties are set for AS3.
# Posted By Seth | 1/23/10 8:52 AM
calvin's Gravatar addChild(preloaderDisplay);

I find this isnt working as before in flex3 for me. I would like to know what to do to stop errors in my application when I try to do addChild, I am prompted to do an addElement but that didn't work either. I am happy to use a.s. instead of mxml just want to get a method for me that will allow me to move past this blocker and actually get some work done..
# Posted By calvin | 5/11/10 3:50 PM
Japan's Gravatar This tut was really helpfull to me. Like the above i had troubles, but running the app and right clicking really helps - might wanne try that.

I got it working i am up to designin my own.

Thanks
# Posted By Japan | 8/5/10 10:21 AM
Lon Hosford's Gravatar When I download the source and import into FlashBuilder and install embedded fonts needed and run it the following security error comes up.

Connection to file:///Users/ahosford/Downloads/Flex4PreloaderExample/bin-debug/textLayout_1.0.0.595.swf halted - not permitted from file:///Users/ahosford/Downloads/Flex4PreloaderExample/bin-debug/Flex4PreloaderExample.swf
SecurityError: Error #2148: SWF file file:///Users/ahosford/Downloads/Flex4PreloaderExample/bin-debug/Flex4PreloaderExample.swf cannot access local resource file:///Users/ahosford/Downloads/Flex4PreloaderExample/bin-debug/textLayout_1.0.0.595.swf. Only local-with-filesystem and trusted local SWF files may access local resources.
   at flash.net::URLStream/load()
   at flash.net::URLLoader/load()
   at mx.core::CrossDomainRSLItem/load()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\core\CrossDomainRSLItem.as:240]
   at mx.core::RSLListLoader/loadNext()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\core\RSLListLoader.as:184]
   at mx.core::RSLListLoader/load()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\core\RSLListLoader.as:156]
   at mx.preloaders::Preloader/initialize()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\preloaders\Preloader.as:279]
   at mx.managers::SystemManager/http://www.adobe.com/2006/flex/mx/internal::initia...()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:1925]
   at mx.managers::SystemManager/initHandler()[E:\dev\4.0.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2419]
[SWF] Users:ahosford:Downloads:Flex4PreloaderExample:bin-debug:Flex4PreloaderExample.swf - 3,394,428 bytes after decompression
# Posted By Lon Hosford | 11/22/10 7:59 AM
Seth's Gravatar @lon see this tutorial as an example. I would suggest that if you are having problems with different Flex4 sdk versions that you start by just using the Preloader.as and place PreloaderDisplay.swc in your libs folder in a new Flex4 project.
# Posted By Seth | 11/22/10 8:23 AM
Lon Hosford's Gravatar I found the problem. The example works fine. Thanks for paying attention to the comment.

The problem was solved by following directions here which amounted to no more than closing all browsers.

http://kb2.adobe.com/cps/518/cpsid_51814.html

Just the machine I am using is set up using Flash Builder on a Mac and not in Eclipse and the flexibility of where projects reside trips you up.
# Posted By Lon Hosford | 11/22/10 1:42 PM
mat's Gravatar Hello,thx for this tuto, it is very great. I have only one question.I just start to work on flex and I want to change the number of the steps in my progress bar.I have found that I need to change initProgressTotal for the total number but I have not found how to call the
event which do progress the bar. Could you help me?
# Posted By mat | 12/23/10 2:42 AM
Naresh's Gravatar hi to all,

Am used that code in flex4 .its working but loading the bar going back and come processing for atleast 6 times.
how to set the one time bar loading in flex
# Posted By Naresh | 3/15/11 4:56 AM
Naresh's Gravatar hi

how to load only one time in flex4
# Posted By Naresh | 3/15/11 4:59 AM
Kenny's Gravatar GREAT WORK!!
I have been working in Flex for the past 7 yrs and previously did Flash since the MX days.
Lost touch with Flash since I got on the Flex band-wagon.
This tutorial is fantastic, took me only a few minutes to grasp what you were accomplishing and after 2 days of beating my head against my monitor on trying to get the preloader built in Flex to work for me (IE hated it), I read your article and knocked out my preloader in 30 minutes.
Thanks for your article - keep up the great work.
Kenny
# Posted By Kenny | 4/1/11 8:42 AM
reza's Gravatar wow thanks great tutorial...easy to implement.
# Posted By reza | 4/22/11 1:47 AM
Rodrigo's Gravatar Hi, Great Tutorial ! How can i show only one 100% and not 3 or 4 ?

Thanks !
# Posted By Rodrigo | 6/23/11 7:28 AM
Jay's Gravatar Thanks for this! I am having a problem though. My entire site loads before showing the preloader for just a split second. Is there any way to ensure that the preloader loads and plays before the main content? I'm working in an existing project in Flash Builder 4.5. Thanks very much.
# Posted By Jay | 7/3/11 11:18 PM
Govind Singh's Gravatar Really great tutorial ..... easy to modify and implement.....
My
# Posted By Govind Singh | 8/1/11 1:05 AM
Anix's Gravatar Hi, Thanks for this tutorial, it's great!
I would like to add a background image, how can I do that?
Thanks
# Posted By Anix | 8/6/11 9:57 PM
Seth's Gravatar Please note there are changes for 4.5

http://forums.adobe.com/message/3700786

Add:


// Override to return true so progress bar appears during initialization.
override protected function showDisplayForInit(elapsedTime:int, count:int):Boolean
{
return true;
}

// Override to return true so progress bar appears during download.
override protected function showDisplayForDownloading(elapsedTime:int, event:ProgressEvent):Boolean
{
return true;
}
# Posted By Seth | 10/31/11 2:31 PM
Manish's Gravatar Thanks for sharing nice post.
# Posted By Manish | 7/26/12 11:23 AM