`
bndis
  • 浏览: 14810 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Building a custom Flex preloader

阅读更多

  http://www.adobe.com/devnet/flex/articles/flex-cus tom-preloader.html Recently I became bored with the standard Flex 4 progress bars and decided to create a custom Flex 4 preloader using Flash Professional CS5 and Flash Builder 4. The example that serves as the basis for this article was inspired by Seth Duffey and the excellent tutorial he wrote on this topic.  His was the only example I found that uses an animation created in Flash to customize the user experience. In this article I'll explain how to extend the classic SparkDownloadProgressBar class to create a custom Flex 4 preloader using a custom animation created in Flash Professional  CS5. I found that the trickiest part of this effort was correctly understanding the behavior of Flash Player when it is loading a Flex 4 application. First, Flash Player loads the SWF application file for example, main.swf. When it discovers that the SWF is a Flex 4 application, it needs to download the Runtime Shared Libraries RSLs of the appropriate framework. Framework RSLs come in two versions: signed and unsigned. If you publish an application with signed RSLs, then they can be cached in a special Flash Player cache and in the browser cache. If you clear the browser's cache, then the RSLs still persist in the special Flash Player cache. If you publish a Flex 4 application with unsigned framework RSLs, then they are cached only in the browser cache and can only be used by applications coming from the same domain. Using unsigned RSLs instead of signed RSLs can dramatically change the end users' experience while loading your Flex 4 application. I've developed a classic Flex 4 sample and published it with unsigned RSLs. Flash Player starts loading the main.swf, and then it loads the RSLs: OSMF, TLF Text Layout Framework, framework, Spark, rpc data services, and sparkskins. The RSLs can be downloaded in parallel. Flash Player can start downloading the unsigned RSLs even if the download of the main application is not complete. As a result the progress bars of the classic Flex 4 preloader might display unexpected behaviors. For example, sometimes the progress bar advances and then goes back or flickers. The default implementation of the SparkDownloadProgressBar uses two tracks. The first track a grey rectangle in the background of the progress bar shows the download progress. The second one shows the initialization progress. I wanted to extend this class for several reasons. First, the download progress track displays mixed information; it shows the download progress of the main application as well as the RSL download progress. The good news is that you can override two separate progress handlers progressHandler for the main app and rslProgressHandler for the RSLs so that you users can see and understand these two steps separately. Second, the new SparkDownloadProgressBar doesn't display any text information although the Flex 3 version did. Before exploring the code, take a look at the final result. Clear your browser's cache and click on the following links in order: Link to the application with unsigned RSLs-Flash Player will load the main application plus six RSLs. 
  Link to the application with signed RSLs-Flash Player should only load the main application and get the RSLs from the Flash Player cache. 
  As you can see, the application does not using the classic progress bar. Instead it uses a custom animation I created in Flash Professional CS5. The white logo appears when the main application is loaded. The ActionScript  function that controls the white logo is setMainProgress. The function setDownloadRSLProgress controls the stroke of the logo plus a glow effect while the RSLs are loaded. Finally, setInitAppProgress is used to fade out the red square during the initialization step see Figure 1. 
  
  To use the download progress animation, you need to extend the SparkDownloadProgressBar class. Then you're free to override the default behavior of methods such as setDownloadprogress, rslProgressHandler, and progressHandler. When the rslProgressHandler method is called, you can get the total number of RSLs to load for your application. To display the global download progress of the RSLs, you can use this function: Math.roundi*100/t + a/t where i is the current index of the loaded RSL, t is the total number of RSLs, and a is the progress download status of the RSL. In the example below, preloaderDisplay is the name of the Flash component. Here is the code for the custom SparkDownloadProgressBar component: /* * Class blogged on RIAgora.com * Inspired by http://www.leavethatthingalone.com/blog/index.cfm/ 2009/11/11/Flex4CustomPreloader */ package com.riagora.loader { import flash.events.Event; import flash.events.ProgressEvent; import flash.utils.getTimer; import mx.events.RSLEvent; import mx.preloaders.SparkDownloadProgressBar; public class Preloader extends SparkDownloadProgressBar { private var _displayStartCount:uint = 0; private var _initProgressCount:uint = 0; private var _downloadComplete:Boolean = false; private var _showingDisplay:Boolean = false; private var _startTime:int; private var preloaderDisplay:PreloaderDisplay; private var rslBaseText:String = "Loading app: "; private var numberRslTotal:Number = 1; private var numberRslCurrent:Number = 1; public function Preloader() { super(); } /** * Event listener for the FlexEvent.INIT_COMPLETE event. * NOTE: This event can be commented out to stop preloader from completing during testing */ override protected function initCompleteHandler(event:Event):void { dispatchEvent(new Event(Event.COMPLETE)); } /** * Creates the subcomponents of the display. */ 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); } } /** * Event listener for the ProgressEvent.PROGRESS event event. * Download of the first SWF app **/ override protected function progressHandler(evt:ProgressEvent):void { if (preloaderDisplay) { var progressApp:Number = Math.round((evt.bytesLoaded/evt.bytesLoaded)*100); //Main Progress displays the shape of the logo preloaderDisplay.setMainProgress(progressApp); setPreloaderLoadingText(rslBaseText + Math.round((evt.bytesLoaded/evt.bytesLoaded)*100). toString() + "%"); }else{ show(); } } /** * Event listener for the RSLEvent.RSL_PROGRESS event. **/ override protected function rslProgressHandler(evt:RSLEvent):void { if (evt.rslIndex && evt.rslTotal) { numberRslTotal = evt.rslTotal; numberRslCurrent = evt.rslIndex; rslBaseText = "loading RSLs (" + evt.rslIndex + " of " + evt.rslTotal + ") "; var progressRsl:Number = Math.round((evt.bytesLoaded/evt.bytesTotal)*100); preloaderDisplay.setDownloadRSLProgress(Math.round ( (numberRslCurrent-1)*100/numberRslTotal + progressRsl/numberRslTotal)); setPreloaderLoadingText(rslBaseText + Math.round((evt.bytesLoaded/evt.bytesTotal)*100).t oString() + "%"); } } /** * indicate download progress. */ override protected function setDownloadProgress(completed:Number, total:Number):void { if (preloaderDisplay) { //useless class in my case. I manage the display changes directly in the Progress handlers } } /** * Updates the inner portion of the download progress bar to * indicate initialization progress. */ override protected function setInitProgress(completed:Number, total:Number):void { if (preloaderDisplay) { //set the initialization progress : red square fades out preloaderDisplay.setInitAppProgress(Math.round((co mpleted/total)*100)); //set loading text if (completed > total) { setPreloaderLoadingText("ready for action"); } else { setPreloaderLoadingText("initializing " + completed + " of " + total); } } } /** * Event listener for the FlexEvent.INIT_PROGRESS event. * This implementation updates the progress bar * each time the event is dispatched. */ override protected function initProgressHandler(event:Event):void { var elapsedTime:int = getTimer() - _startTime; _initProgressCount++; if (!_showingDisplay && showDisplayForInit(elapsedTime, _initProgressCount)) { _displayStartCount = _initProgressCount; show(); // If we are showing the progress for the first time here, we need to call setDownloadProgress() once to set the progress bar background. setDownloadProgress(100, 100); } if (_showingDisplay) { // if show() did not actually show because of SWFObject bug then we may need to set the download bar background here if (!_downloadComplete) { setDownloadProgress(100, 100); } setInitProgress(_initProgressCount, initProgressTotal); } } private function show():void { // swfobject reports 0 sometimes at startup // if we get zero, wait and try on next attempt if (stageWidth == 0 && stageHeight == 0) { try { stageWidth = stage.stageWidth; stageHeight = stage.stageHeight } catch (e:Error) { stageWidth = loaderInfo.width; stageHeight = loaderInfo.height; } if (stageWidth == 0 && stageHeight == 0) return; } _showingDisplay = true; createChildren(); } private function setPreloaderLoadingText(value:String):void { //set the text display in the flash SWC preloaderDisplay.loading_txt.text = value; } } }
  If you want to explore the source code of the sample application, download the sample ZIP file for this article, start Flash Builder, and then choose File > Import > Flash Builder Project to import the project. You can also watch this video in which I summarize how I built the custom Flex 4 preloader for this article and show a demonstration of it running.
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics