views:

8942

answers:

7

Hello friends!

I'm trying to create / use a pre-loader in my flex application. The preloader is a SWF file which has 100 frames (1 for every percent of the loader progress). Basically I am trying to Embed this SWF file in my application, display it on screen and change the frame number being displayed as the progress completes.

The code I have so far is (which extends Canvas):

[Embed("/../assets/preLoader.swf")]
private var SWFClass:Class;

private var _preLoader:MovieClip;

private var _progress:Number;

public function set progress(value:Number) : void {
    _progress = value;

    if(progress < 100) {
     _preLoader.gotoAndPlay(progress, null);
    }else {
     _preLoader.gotoAndStop(0, null);
    }
}   

[Bindable]
public function get progress() : Number {
    return _progress;
}



(Called on creationComplete event)    
private function init() : void {
    _preLoader = MovieClip(new SWFClass());

    this.addChild(_preLoader);

    _preLoader.play();
}

The error I am getting is:

TypeError: Error #1034: Type Coercion failed: cannot convert widgets::PreLoader_SWFClass@30b3be51 to mx.core.IUIComponent.at mx.core::Container/http://www.adobe.com/2006/flex/mx/internal::addingChild()[C:\autobuild\3.2.0\frameworks\projects\framework\src\mx\core\Container.as:3259]

Please help!

+1  A: 

You need to have a wrapper over MovieClip that implements the IUIComponent in order to be able to pass to addChild(). From the addChild() documentation:

Note: While the child argument to the method is specified as of type DisplayObject, the argument must implement the IUIComponent interface to be added as a child of a container. All Flex components implement this interface.

You will need something like this:

public class MovieClipUIComponent extends UIComponent {
   public function MovieClipUIComponent (mc:MovieClip) {
      super ();

      mcHeight = mc.height;
      mcWidth = mc.width;

      // add your own magic

      addChild (mc);
   }
}

Warning: Untested code, should give you an idea only!

dirkgently
Hi, thanks for your answer. Is there no work-around documented anywhere for this? :s Seems a bit strange. Cheers.
Richie_W
It is fairly trivial to implement a wrapper. See hint in my updated answer.
dirkgently
A: 

Use sprite instead of Canvas as a base class. Two reasons to do this:

  1. Canvas has a lot of dependencies (to the tune of 100k+ of flex components). You don't want to wait for all this to load before displaying your preloader

  2. Canvas is UIComponent container. Use it when you want to lay out UIComponents. In your case, you do not need complicated canvas layout logic - you just need to display a MovieClip. So don't use a canvas.

To answer your original question, SWFLoader and Image are UIComponents that know how to display Bitmaps and MovieClips. Do something like this instead:

var img:Image = new Image();
img.source = _preloader;
this.addChild(img);
Brian
I was meaning to update this question with this method at some point. That's exactly what I ended up doing. Thanks.
Richie_W
A: 

Have a look at the the Preloader class and the preloader property of the Application class.

As the documentation says, you definitely shouldn't extend the Flex UIComponent (or Image or SWFLoader) classes for a preloader.

Here are a few examples of how to go about customising the preloader:

http://www.pathf.com/blogs/2008/08/custom-flex-3-lightweight-preloader-with-source-code/

http://groups.adobe.com/posts/15d371c71d

http://www.webapper.net/index.cfm/2008/1/17/Flex-NotSo-Custom-Preloader

Sly_cardinal
A: 

@ dirkgently

Your code worked! thanks!!

A: 

i found custom preloader using external swf code from this link
http://askmeflash.com/article_m.php?p=article&amp;id=7

A: 

Hi All, I have a problem with this code:

var container:MovieClip = this.createEmptyMovieClip("c", 100); //btn is the instance name on the stage. btn.onPress = function() { container.gotoAndPlay(2); };

If I upload the file to flashDuniya server then it's working fine but it's running to other server. while flashduniya/crossdomain.xml has the access for all. Any one can tell me the solution?

A: 

Hope this work I tried this.

[Embed(source="assets/yourSWF.swf", mimeType="application/octet-stream")] public var SWF:Class;


_swfLoader = new Loader(); //nothing to do onComplete or onProgress method just to debug // Add complete event listener _swfLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete); // Add progress event listener _swfLoader.contentLoaderInfo.addEventListener(ProgressEvent.PROGRESS, onProgress);

// Add error event listener. Critical if you don't want run time errors if there // are problems loading the file. _swfLoader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);

// Incase of loading Flex. Very important. _swfLoader.addEventListener("mx.managers.SystemManager.isBootstrapRoot", systemManagerHandler); _swfLoader.addEventListener("mx.managers.SystemManager.isStageRoot", systemManagerHandler);

// Load on the loader with a new URLRequest instance passing the path to // it's constructor. _swfLoader.loadBytes(new SWF());

// We have to addd the loader so it creation is done. addChild(_swfLoader);


private function systemManagerHandler(e:Event):void { // Prevent default stops default behaviour here and thus stops some potential // run time errors.
e.preventDefault(); }

Jatin