【转】Flex 预载界面美化

转自http://riashanghai.com/zh-hant/node/48

 

Flex 的默认的 Preloader, 平心而论,不是很好看。一个个性化的Preloader,基本上要包括三个部分。png-1743

1. 公司或者网站Logo,或者个性化的预载图片。好似是桌面软件的Splash Screen。

2. 载入数据的进度,文字形式的百分比。

3. 载入进度条。

preloader不像Flex项目中普通的部件可以通过CSS进行设置,是因为当程序初始载入时,CSS文件的设定还未被载入,所以不好通过CSS进行外观的控制。

这里有Ted把SWF,GIF 和 PNG 文件作为 Preloader 的教程。不过这里没有上述元素三合一的例子。

把网上的资料总结一下,这里放个三合一的例子。最终效果预览,

loader

 

设置WEB程序的Preloader为自制的Preloader时,要修改主程序Application标签中的preloader属性,

 

  1. <?xml version="1.0" encoding="utf-8"?>   
  2. <MX:APPLICATION layout="absolute" xmlns:mx="http://www.adobe.com/2006/mxml" preloader="com.ibsol.view.Preloader">   
  3. <MX:SCRIPT>   
  4. ...</MX:SCRIPT></MX:APPLICATION>  

 

这里的com.ibsol.view.Preloader是自定义Preloader类的路径。

Preloader要扩展DownloadProgressBar类才能设置自己的Preloader

 

  1. package com.ibsol.view   
  2. {   
  3.     import flash.display.Sprite;   
  4.     import flash.events.Event;   
  5.     import flash.events.ProgressEvent;   
  6.     import flash.events.TimerEvent;   
  7.     import flash.text.TextField;   
  8.     import flash.utils.Timer;   
  9.     import mx.events.FlexEvent;   
  10.     import mx.preloaders.DownloadProgressBar;   
  11.        
  12.     public class Preloader extends DownloadProgressBar   
  13.     {   
  14.         //显示进度的文字   
  15.         private var progressText:TextField;   
  16.         //进度条   
  17.         public var img:WelcomeScreen;   
  18.         //logo页面   
  19.         public var logo:WelcomeLogo;   
  20.         private var _timer:Timer;   
  21.            
  22.         public function Preloader()   
  23.         {   
  24.             super();   
  25.             //加入logo   
  26.             logo = new WelcomeLogo();   
  27.             this.addChild(logo);   
  28.             //加入进度条   
  29.             img = new WelcomeScreen();   
  30.             this.addChild(img);   
  31.             //加入进度文字   
  32.             progressText = new TextField();   
  33.             progressText.x = 40;   
  34.             progressText.y = 90;   
  35.             this.addChild(progressText);   
  36.             //进度条计时器初始化,我们实现进度条的原理就是不停的刷新进图条图片   
  37.             //因为每次进度条的长度不同,所以就有进度条在走的效果   
  38.             _timer = new Timer(1);   
  39.             _timer.addEventListener(TimerEvent.TIMER, drawTimerHandler);   
  40.             _timer.start();   
  41.         }   
  42.         /**  
  43.          * override这个函数,来实现自己Preloader的设置,而不是用其默认的设置  
  44.          */  
  45.         override public function set preloader(value:Sprite):void  
  46.         {   
  47.             value.addEventListener(ProgressEvent.PROGRESS, progHandler);   
  48.             value.addEventListener(FlexEvent.INIT_COMPLETE, initCompleteHandler);   
  49.             //在这里设置预载界面居中   
  50.             //如果在初始化函数中设置,会有stageWidth和最终界面大小不一致的错误,而导致不能居中   
  51.             x = (stageWidth/2) - (300/2);   
  52.             y = (stageHeight/2) - (180/2);   
  53.         }   
  54.            
  55.         private function progHandler(e:ProgressEvent):void  
  56.         {   
  57.             //计算进度,并且设置文字进度和进度条的进度。   
  58.             var prog:Number = e.bytesLoaded/e.bytesTotal*100;   
  59.             progressText.text = "已下载 " + String(int(prog)) + "%";   
  60.             if(img)   
  61.             {   
  62.                 img.progress = prog;   
  63.             }   
  64.         }   
  65.            
  66.         private function compHandler(e:Event):void  
  67.         {   
  68.                
  69.         }   
  70.            
  71.         private function initCompleteHandler(e:FlexEvent):void  
  72.         {   
  73.             //如果载入完毕,则停止刷新   
  74.             img.ready = true;   
  75.             _timer.stop();   
  76.             //测试专用。下载完毕后,不马上跳到程序的默认界面。而是停顿10秒后再跳入。   
  77.             var timer:Timer = new Timer(10000, 1);   
  78.             timer.addEventListener(TimerEvent.TIMER, dispatchComplete);   
  79.             timer.start();   
  80.         }   
  81.            
  82.         private function initProgHandler(e:FlexEvent):void  
  83.         {   
  84.                
  85.         }   
  86.         /**  
  87.          * 一定要分发这个事件,来通知程序已经完全下载,可以进入程序的默认界面了  
  88.          */  
  89.         private function dispatchComplete(event:TimerEvent):void  
  90.         {   
  91.             this.dispatchEvent(new Event(Event.COMPLETE));   
  92.         }   
  93.         /**  
  94.         * 每个时钟周期都刷新进度条图片  
  95.         */  
  96.         private function drawTimerHandler(event:TimerEvent):void  
  97.         {   
  98.             img.refresh();   
  99.         }   
  100.   
  101.     }   
  102. }  

图片logo层的实现方式是

 

  1. package com.ibsol.view   
  2. {   
  3.     import flash.display.Loader;   
  4.     import flash.utils.ByteArray;   
  5.        
  6.     public class WelcomeLogo extends Loader   
  7.     {   
  8.         [Embed(source="assets/preloader.png", mimeType="application/octet-stream")]   
  9.         public var WelcomeScreenGraphic:Class;   
  10.         public function WelcomeLogo()   
  11.         {   
  12.             this.loadBytes(new WelcomeScreenGraphic() as ByteArray);   
  13.         }   
  14.   
  15.     }   
  16. }  

 

进度条和图片可以放在一层,但是考虑到个时钟周期,都要刷新进度条的图片。

毕竟LOGO不用每次都刷新,那么我们就分开放置了。进度条层的代码如下,

 

  1. package com.ibsol.view   
  2. {   
  3.     import flash.display.BitmapData;   
  4.     import flash.display.Graphics;   
  5.     import flash.display.Loader;   
  6.     import flash.display.Sprite;   
  7.     import flash.utils.ByteArray;   
  8.        
  9.     import mx.graphics.codec.PNGEncoder;   
  10.        
  11.     public class WelcomeScreen extends Loader   
  12.     {   
  13.         //辅助属性,帮助进行进度条的定位   
  14.         private static var _LogoWidth:int = 300;   
  15.         private static var _LogoHeight:int = 180;   
  16.         private static var _LeftMargin:int = 5;   
  17.         private static var _RightMargin:int = 5;   
  18.         private static var _TopMargin:int = 1;   
  19.         private static var _BottomMargin:int = 1;   
  20.         private static var _Padding:int = -60;   
  21.         //Progress bar settings   
  22.         //进度条的设定,比如显色边框等   
  23.         private static var _BarWidth:int = 200;   
  24.         private static var _BarHeight:int = 12;   
  25.         private static var _BarBackground:uint  = 0xFFFFFF;   
  26.         private static var _BarOuterBorder:uint = 0x737373;   
  27.         private static var _BarColor:uint = 0x6F9FD5;   
  28.         private static var _BarInnerColor:uint = 0xFFFFFF;   
  29.            
  30.         private var isReady:Boolean = false;   
  31.         public  var progress:Number;   
  32.         private var _logoData : BitmapData;   
  33.            
  34.         public function WelcomeScreen()   
  35.         {   
  36.             //this.loadBytes(new WelcomeScreenGraphic() as ByteArray);   
  37.         }   
  38.            
  39.         override public function get width() : Number   
  40.         {   
  41.             return Math.max(_BarWidth, _LogoWidth) + _LeftMargin + _RightMargin;   
  42.         }   
  43.            
  44.         override public function get height() : Number   
  45.         {   
  46.             return _LogoHeight + _BarHeight + _Padding + _TopMargin + _BottomMargin;   
  47.         }   
  48.         /**  
  49.         * 进度载入完毕后,隐藏进度条  
  50.         */  
  51.         public function set ready(value : Boolean) : void  
  52.         {   
  53.             this.isReady = value;   
  54.             this.visible = !this.isReady;   
  55.         }   
  56.            
  57.         public function get ready() : Boolean { return this.isReady; }   
  58.         /**  
  59.         * 刷新函数,每个时钟周期都被调用的函数  
  60.         */  
  61.         public function refresh():void  
  62.         {   
  63.             _logoData = this.drawProgressBar();   
  64.             var encoder:PNGEncoder = new PNGEncoder();   
  65.             this.loadBytes(encoder.encode(_logoData));   
  66.         }   
  67.         /**  
  68.         * 进度条生成函数  
  69.         */  
  70.         private function drawProgressBar():BitmapData   
  71.         {   
  72.             // create bitmap data to create the data   
  73.             var data : BitmapData = new BitmapData(this.width, this.height, true, 0);   
  74.             // draw the progress bar   
  75.             var s:Sprite = new Sprite();   
  76.             var g:Graphics = s.graphics;   
  77.             // draw the bar background   
  78.             g.beginFill(_BarBackground);   
  79.             g.lineStyle(2, _BarOuterBorder, 1, true);   
  80.             var px : int = (this.width - _BarWidth) / 2;   
  81.             var py : int = _TopMargin + _LogoHeight + _Padding;   
  82.             g.drawRoundRect(px, py, _BarWidth, _BarHeight, 2);   
  83.             var containerWidth : Number = _BarWidth - 4;   
  84.             var progWidth:Number = containerWidth * this.progress / 100;   
  85.             g.beginFill(_BarColor);   
  86.             g.lineStyle(1, _BarInnerColor, 1, true);   
  87.             //根据progress进度,来画出进度条的长度   
  88.             g.drawRect(px + 1, py + 1, progWidth, _BarHeight - 3);   
  89.             data.draw(s);   
  90.             return data;   
  91.         }   
  92.   
  93.     }   
  94. }  

 

部分代码非原创,不过注释是原创,呵呵,可以参考 Josh's Blog

posted on 2009-06-05 16:40  小龙龙  阅读(443)  评论(0编辑  收藏  举报

导航