Click here to ask Question NowIts free No registration required. Flash, Flex, Flash
Media Server, ActionScript,Adobe Air. Most questions receive a response in an hour.
Title:
Custom preloader - progress bar flex by Inder
I implemented this custom preloader made by Inder and posted on this site.
However, it doesn't work properly for me. I get an TypeError #2007 Parameter child can not be non-null . But when I do a refresh of my page, it eventually works. I think it is a problem with his scripting (bytesloaded etc ...)
Hi Bartman the code does not seems to have any such problem , Many people have successfully implemented and told me about that. How ever I would like to know why this problem is occurring at your end. Have you altered anything in the code ?
The error you mentioned occurs when something is accessed before its loaded . in your case it seems that when you first run application the object does not load , because it might be some external content and second time it works fine because its cached by browser and is accessible immediately.
1) I made a reference to my own progress bar
2) I made the progress bar design 400px instead of 200px
I use adobe flex builder 3. And what you said i absolutely true, the first run it doesn't work and second time it works because it's cached.
package preload
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.ByteArray;
import flash.utils.Timer;
import mx.preloaders.DownloadProgressBar;
/*#########################################################################
Class created for http://askmeflash.com
get answers to all your flash, flex, FMS problems at askmeflash.com its free
Flash developers website http://askmeflash.com
##########################################################################*/
public class CustomPreloader extends DownloadProgressBar {
private var timer:Timer;
//progress bar
private var pBar:Sprite= new Sprite();
//Progress bar mask
private var maskBar:Sprite= new Sprite();
//Text box to diplay loading percentage
private var txtBox:TextField = new TextField();
//loader for loading swf design of progress bar
private var loader:Loader;
//Load swf file containing design of progress bar
[ Embed(source="blueBar.swf", mimeType="application/octet-stream") ]
public var WelcomeScreenGraphic:Class;
//background color
private var bgSprite:Sprite= new Sprite();
private var txtFormat:TextFormat;
public function CustomPreloader()
{
this.addChild(bgSprite);
//timer
timer = new Timer(1);
timer.addEventListener(TimerEvent.TIMER, drawProgress );
timer.start();
//loading swf file of progress bar design
loader= new Loader();
loader.loadBytes( new WelcomeScreenGraphic() as ByteArray );
pBar.addChild(loader);
this.addChild(txtBox);
pBar.addChild(maskBar);
pBar.mask=maskBar;
//position textbox
txtBox.textColor=0xffffff;
txtFormat= new TextFormat();
txtFormat.font="Arial";
//background color of preloader
bgSprite.graphics.beginFill(0x000000);
bgSprite.graphics.drawRect(0,0,200,200)
bgSprite.graphics.endFill();
}
override public function set preloader( preloader:Sprite ):void
{
preloader.addEventListener(ProgressEvent.PROGRESS, SWFDownloadProgress);
//position progressbar to center of stage
var centerX:Number=(this.stage.stageWidth - 475) / 2;
var centerY:Number=(this.stage.stageHeight - 153) / 2;
pBar.x = centerX;
pBar.y = centerY;
txtBox.x=centerX+6;
txtBox.y=centerY-14;
bgSprite.width=this.stage.stageWidth;
bgSprite.height=this.stage.stageHeight;
this.addChild(pBar);
}
private var progress:Number;
private function SWFDownloadProgress( event:ProgressEvent ):void {
//progress multiplied by 2 cos our progress bar design is 200 px
var multiplier:Number=4;
progress=multiplier*Number(event.target.loaderInfo.bytesLoaded/event.target.loaderInfo.bytesTotal*100);
}
private var currlen:Number=0;
public function drawProgress(event: Event):void{
//change the mask color to the color of your background
if(currlen<progress){
currlen+=1;
maskBar.graphics.beginFill(0x0000ff);
maskBar.graphics.drawRect(0,0,currlen+10,400);
maskBar.graphics.endFill();
txtBox.text="Loading.."+Math.round(currlen/4)+"%";
txtBox.setTextFormat(txtFormat);
}
if(currlen==400){
timer.stop();
dispatchEvent( new Event( Event.COMPLETE ) );
}
}
}
}
TypeError: Error #2007: Parameter child mag niet null zijn.
at flash.display::DisplayObjectContainer/addChildAt()
at mx.managers::SystemManager/preloader_preloaderDoneHandler()
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.preloaders::Preloader/displayClassCompleteHandler()
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at preload::CustomPreloader/drawProgress()
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
I have checked by copying your whole code and tested local as well as on my website online clearing cache, browser firefox and IE, but error is no occurring at my end.I am using flex sdk 3.4, but i have also tested in flex 4 also.
If you are using debug version then it should through error with line number. See if you can get the complete error. If you can provide me the online link then i can see it there , remember to upload the debug version not the release, so i can see the error.
It seems to me some internal error of application, you can test that by using a fresh application and implementing loader in that. Do not write anything else in that application, if the error is ion this class then it will throw error.
:) Last alternative , if you can share the project or the sample project that gives error , then i will try to find out.
ok, see when this class dispatches " dispatchEvent( new Event( Event.COMPLETE ) ); "
the application is added and then initialized. So if there is an problem inside the application , it occurs just after dispatching this event. According to error the "drawProgress()" function triggered the preloader complete event which means functionality of preloader class is over and its removed automatically after that.
You can comment the "dispatchEvent( new Event( Event.COMPLETE ) ); "
line, This will make preloader to complete the progress but will not launch the application , If preloader reaches 100% it means the class is working fine and you should look inside the application for the problem. Let me know whats the status , if not fixed then share me your project :)
Ok I commented out the "dispatchEvent( new Event( Event.COMPLETE ) ); " and the loader reaches 100%, so the problem is in my application. I am uploading the bin-debug at this moment (www.vlmr.be)
i am getting error every time the complete error with line number is :
TypeError: Error #2007: Parameter child must be non-null.
at flash.display::DisplayObjectContainer/addChildAt()
at mx.managers::SystemManager/preloader_preloaderDoneHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\managers\SystemManager.as:2980]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at mx.preloaders::Preloader/displayClassCompleteHandler()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\preloaders\Preloader.as:434]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at preload::CustomPreloader/drawProgress()[C:\Users\Bart\Documents\Flex Builder 3\VLMR\src\preload\CustomPreloader.as:95]
at flash.utils::Timer/_timerDispatch()
at flash.utils::Timer/tick()
After looking at "Preloader.as:434" line number i can see that the error is due to RSL, You must be using the RSL , have you uploaded the RSL file on the required location online ?.
The error occurred shows that RSL loading failed with 0 bytes downloaded. RSL can be set in the project properties , see the first point of this article to know how its implemented
http://askmeflash.com/article/9/optimize-flex-swf-filesize-performance-loading
also check your application by removing preloader class if it works
flash player is different for ie and firefox , so the RSL copy must be present with IE , you need to keep a copy of rsl file created , on your website so that if its not present in the flash player it can be downloaded . copy it from your bin folder to your site
file name is something like "framework_3.2.0.3958.swz"
I already have framework_3.2.0.3958.swz on my server .
So that is not the solution for Firefox and Safari. If you don't mind, you may always give me your email address or facebook/msn. It's always nice to have a pro flex programmer as a friend ;) .
I'm going to bed now, hopefully we can speak again tomorrow !
Thank you so much for all your effort Inder, really appreciate it !!
I mean to say was your application working fine without this preloader class , Just remove the preloader="preload.CustomPreloader" from your application tag and see if your application works fine? This will rule out whether any conflict is occurring due to using a custom preloader class.
I think I was a little bit too fast with saying that it works in Internet Explorer. I am at my work now and I tested it on 2 pc's (both with Internet Explorer) and it doesn't work. The main application is again not fully loaded, i hit f5, it refreshes and it eventually works.
When I remove the preloader property from the application tag, it works but it loads slowly with the default preloader.
I shared my project:
http://www.filefactory.com/file/b22e116/n/bin-debug.rar ->> here is my project
I you have the time I would appreciate if you have a look at it.
hi checked your project its a compiled version so I cant do any thing with that to debug. You need to upload the project source. Delete the assets folder from zip file before uploading . it contains videos which are not required for debugging , remaining project is just 3- 4 MB.
Hi bartman, got the code. I have resolved the problem with the trick, and that is you need to delay the dispatchEvent using the following code inside "drawProgress90" function, also declaclare a variable "timeDelay" Number type outside the function.
timeDelay +=1;
// you can decrease the delay value (500) to see if it works for you
if(timeDelay > 500){
timer.stop();
dispatchEvent( new Event( Event.COMPLETE ) );
}
Technically the problem should not be there, I noticed that after the content is loaded by loader its not immediately available to be initialized. The reason could be big size of swf. So after loading I delayed it a little bit. For the time being you can use this code , i will go in depth to find why this occurred.
Do you mean the drawProgress function, because I can't find a drawProgress90 function inside customPreloader.as. If it is inside the drawProgress function, do i have to replace this code
public function drawProgress(event: Event):void{
//change the mask color to the color of your background
if(currlen<progress){
currlen+=1;
maskBar.graphics.beginFill(0x0000ff);
maskBar.graphics.drawRect(0,0,currlen+10,400);
maskBar.graphics.endFill();
txtBox.text="Loading.."+Math.round(currlen/4)+"%";
txtBox.setTextFormat(txtFormat);
}
if(currlen==400){
timer.stop();
dispatchEvent( new Event( Event.COMPLETE ) );
}
}
with this code
public function drawProgress(event: Event):void{
//change the mask color to the color of your background
if(currlen<progress){
currlen+=1;
maskBar.graphics.beginFill(0x0000ff);
maskBar.graphics.drawRect(0,0,currlen+10,400);
maskBar.graphics.endFill();
txtBox.text="Loading.."+Math.round(currlen/4)+"%";
txtBox.setTextFormat(txtFormat);
}
timeDelay +=1;
// you can decrease the delay value (500) to see if it works for you
if(timeDelay > 500){
timer.stop();
dispatchEvent( new Event( Event.COMPLETE ) );
}
}
sorry its drawProgress() and the updated code is following
private var timeDelay:Number=0;
public function drawProgress(event: Event):void{
//change the mask color to the color of your background
if(currlen<progress){
currlen+=1;
maskBar.graphics.beginFill(0x0000ff);
maskBar.graphics.drawRect(0,0,currlen+10,400);
maskBar.graphics.endFill();
txtBox.text="Loading.."+Math.round(currlen/4)+"%";
txtBox.setTextFormat(txtFormat);
}
if(currlen==400){
timeDelay +=1;
// you can decrease the delay value (500) to see if it works for you
if(timeDelay > 500){
timer.stop();
dispatchEvent( new Event( Event.COMPLETE ) );
}
}
I inserted the code like you said. In firefox it is working perfect now, but in Internet Explorer and Safari the counter keeps going. Instead that it stops at 100%, it keeps counting...
My Code:
private var timeDelay:Number=0;
public function drawProgress(event: Event):void{
//change the mask color to the color of your background
if(currlen<progress){
currlen+=1;
maskBar.graphics.beginFill(0x0000ff);
maskBar.graphics.drawRect(0,0,currlen+10,400);
maskBar.graphics.endFill();
txtBox.text="Loading.."+Math.round(currlen/4)+"%";
txtBox.setTextFormat(txtFormat);
}
if(currlen==400){
timeDelay +=1;
txtBox.text="Initializing VLMR...";
txtBox.setTextFormat(txtFormat);
// you can decrease the delay value (500) to see if it works for you
if(timeDelay > 2500){
timer.stop();
dispatchEvent( new Event( Event.COMPLETE ) );
}
}
}
}
}
I checked , it as you said the preloader was not stopping in IE, I compiled the same code but it worked fine . I have also uploaded the zip file containing my compiled swf , you can upload and check that on your website.
After testing my swf files try this code .I have updated some more code try this code now
package preload
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.ByteArray;
import flash.utils.Timer;
import mx.preloaders.DownloadProgressBar;
/*###############################################################
Class created for http://askmeflash.com
get answers to all your flash, flex, FMS problems at askmeflash.com its free
Flash developers website http://askmeflash.com
################################################################*/
public class CustomPreloader extends DownloadProgressBar {
private var timer:Timer;
//progress bar
private var pBar:Sprite= new Sprite();
//Progress bar mask
private var maskBar:Sprite= new Sprite();
//Text box to diplay loading percentage
private var txtBox:TextField = new TextField();
//loader for loading swf design of progress bar
private var loader:Loader;
//Load swf file containing design of progress bar
[ Embed(source="greenBar.swf", mimeType="application/octet-stream") ]
public var WelcomeScreenGraphic:Class;
//background color
private var bgSprite:Sprite= new Sprite();
private var txtFormat:TextFormat;
public function CustomPreloader()
{
this.addChild(bgSprite);
//timer
timer = new Timer(1);
timer.addEventListener(TimerEvent.TIMER, drawProgress );
timer.start();
//loading swf file of progress bar design
loader= new Loader();
loader.loadBytes( new WelcomeScreenGraphic() as ByteArray );
pBar.addChild(loader);
this.addChild(txtBox);
pBar.addChild(maskBar);
pBar.mask=maskBar;
//position textbox
txtBox.textColor=0xffffff;
txtFormat= new TextFormat();
txtFormat.font="Arial";
//background color of preloader
bgSprite.graphics.beginFill(0x000000);
bgSprite.graphics.drawRect(0,0,200,200)
bgSprite.graphics.endFill();
}
public var myPreloader:Sprite;
override public function set preloader( preloader:Sprite ):void
{
myPreloader=preloader;
preloader.addEventListener(ProgressEvent.PROGRESS, SWFDownloadProgress);
//position progressbar to center of stage
var centerX:Number=(this.stage.stageWidth - 475) / 2;
var centerY:Number=(this.stage.stageHeight - 153) / 2;
//position progress bar
pBar.x = centerX;
pBar.y = centerY;
//position percentage textbox
txtBox.x=centerX+6;
txtBox.y=centerY-14;
bgSprite.width=this.stage.stageWidth;
bgSprite.height=this.stage.stageHeight;
this.addChild(pBar);
}
private var progress:Number;
private function SWFDownloadProgress( event:ProgressEvent ):void {
//progress multiplied by 2 cos our progress bar design is 200 px
var multiplier:Number=4;
progress=multiplier*Number(event.target.loaderInfo.bytesLoaded/event.target.loaderInfo.bytesTotal*100);
}
private var currlen:Number=0;
private var timeDelay:Number=0;
public function drawProgress(event: Event):void{
//change the mask color to the color of your background
if(currlen<progress){
currlen+=1;
maskBar.graphics.beginFill(0x0000ff);
maskBar.graphics.drawRect(0,0,currlen+10,400);
maskBar.graphics.endFill();
txtBox.text="Loading.."+Math.round(currlen/4)+"% ";
txtBox.setTextFormat(txtFormat);
}
if(currlen==400){
if(myPreloader.loaderInfo.bytesTotal == myPreloader.loaderInfo.bytesLoaded){
timeDelay +=1;
if(timeDelay > 500){
timer.stop();
dispatchEvent( new Event( Event.COMPLETE ) );
}
}
}
}
}
}
I tried your code, but I have the same problem in IE and Safari. The counter keeps counting over the 100%. I also uploaded your code, you can test it here:
www.vlmr.be/test/VLMR.html
Your code has the same problem when I open it in IE or Safari, it keeps counting -> 100% 110% 150% ... 500% ...
So weird that is does work in Firefox but not in the other two browser. I'm really stuck now
I found why in IE it keeps counting. The value of 'progress' = Infinity
So the function does: if (currlen < infinity) ... that why it's keep counting. I have no idea why it does that tough.
event.target.loaderInfo.bytesTotal returns 0 . So there is a dividedbyzero problem and that's why it keeps counting. I tried root.loaderInfo.bytesTotal but that doesn't work either. For some reason I cannot ask my bytesTotal in Flex.
I'm trying to find a solution the whole day now, but still nothing.
Hi bartman , this is really a weird problem . I tested the zip file that I sent you from this localtion http://websoftglobal.com/a/vlmr.html, see if it works from your browser, it is working fine on my machine , check if it works from your browsers.
To remove that vertical line , use graphics.clear in drawProgress function just above the beginfill line like this :
hi Inder, i also face the same problem like bartman, the screen become blank after preloader finish loading, and i need to refresh the browser so the main interface will show after preloader finish loading. I hope u can give me some ideas how to solve this problem..
thank you very2 much Inder, you help me to solve the problem..u are great man..
thank you very2 much again..(apologize me because my english not so good)
Hi inder, I want to ask you again about the preloader. How to make the preloader auto-align to always center based on the browser size. I noticed that when we reduced the size of browser while the preloader loading, it did not re-align but still at there. Do you have an idea on how to solve this problem?
Hi inder, I have try your suggestion but it still same. The preloader still did not re-align when i resize the browser either horizontally or vertically. Here is my code:
package com.preload
{
import flash.display.Loader;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.text.TextField;
import flash.text.TextFormat;
import flash.utils.ByteArray;
import flash.utils.Timer;
import mx.preloaders.DownloadProgressBar;
/*#########################################################################
Class created for http://askmeflash.com
get answers to all your flash, flex, FMS problems at askmeflash.com its free
Flash developers website http://askmeflash.com
##########################################################################*/
public class CustomPreloader extends DownloadProgressBar {
private var timer:Timer;
//progress bar
private var pBar:Sprite= new Sprite();
//Progress bar mask
private var maskBar:Sprite= new Sprite();
//Text box to diplay loading percentage
private var txtBox:TextField = new TextField();
//loader for loading swf design of progress bar
private var loader:Loader;
//Load swf file containing design of progress bar
[ Embed(source="greenBar.swf", mimeType="application/octet-stream") ]
public var WelcomeScreenGraphic:Class;
//background color
private var bgSprite:Sprite= new Sprite();
private var txtFormat:TextFormat;
public function CustomPreloader()
{
this.addChild(bgSprite);
//timer
timer = new Timer(1);
timer.addEventListener(TimerEvent.TIMER, drawProgress );
timer.start();
//loading swf file of progress bar design
loader= new Loader();
loader.loadBytes( new WelcomeScreenGraphic() as ByteArray );
pBar.addChild(loader);
this.addChild(txtBox);
pBar.addChild(maskBar);
pBar.mask=maskBar;
//position textbox
txtBox.textColor=0xffffff;
txtFormat= new TextFormat();
txtFormat.font="Arial";
//background color of preloader
bgSprite.graphics.beginFill(0x000000);
bgSprite.graphics.drawRect(0,0,200,200)
bgSprite.graphics.endFill();
}
override public function set preloader( preloader:Sprite ):void
{
preloader.addEventListener(ProgressEvent.PROGRESS, SWFDownloadProgress);
//position progressbar to center of stage
var centerX:Number=(this.stage.stageWidth - 275) / 2;
var centerY:Number=(this.stage.stageHeight - 68) / 2;
pBar.x = centerX;
pBar.y = centerY;
txtBox.x=centerX+6;
txtBox.y=centerY-14;
bgSprite.width=this.stage.stageWidth;
bgSprite.height=this.stage.stageHeight;
this.addChild(pBar);
}
private var progress:Number;
private function SWFDownloadProgress( event:ProgressEvent ):void {
//progress multiplied by 2 cos our progress bar design is 200 px
var multiplier:Number=2;
progress=multiplier*Number(event.target.loaderInfo.bytesLoaded/event.target.loaderInfo.bytesTotal*100);
}
private var currlen:Number=0;
private var timeDelay:Number=0;
public function drawProgress(event: Event):void{
//change the mask color to the color of your background
if(currlen<progress){
currlen+=1;
maskBar.graphics.beginFill(0x0000ff);
maskBar.graphics.drawRect(0,0,currlen+10,200);
maskBar.graphics.endFill();
txtBox.text="Loading..."+Math.round(currlen/2)+"%";
txtBox.setTextFormat(txtFormat);
}
if(currlen==200){
timeDelay +=1;
if(timeDelay > 50){
timer.stop();
dispatchEvent( new Event( Event.COMPLETE ) );
}
}
}
}
}
I'm sorry for the code, I had adjusted it to make sure the code easy for you to read but after I posted it, the code did not aligned well..apologize me..and hope you can help me...