[转]Preloader-Flex自定义预载进度条
当网络速度较慢时,如果在下载过程中界面没有任何的提示或变化,用户会感到烦躁,甚至抱怨开发商,这不是我们所希望的。进度条是很好的转移注意力的方式,它让用户感觉到程序在正常运转,可以耐心地等下去。
Preloader就是这样一个类,它负责监听Application、RSL和模块的下载和初始化进程的状态,包括对下载过程的监听,并且根据下载的状态生成相应的初始化进程事件,包括:
FlexEvent.INIT_PROGRESS
FlexEvent.INIT_COMPLETE
ProgressEvent.PROGRESS
Event.COMPLETE
Preloader虽然发布初始化进程事件,但是并不直接显示初始化进程,而是把显示的工作交给一个显示类来完成,我们称这个类为加载显示类。SystemManager在自己的initialize方法中会调用Preloader的initialize方法,并把加载显示类的类名作为参数值传递给Preloader。在默认情况下,这个类被SystemManager指定为DownloadProgressBar(系统默认的进度条)。
如果我们在mx:application标记中使用preloader属性指定加载显示类,那么指定的类名将作为参数传递给Preloader。Preloader类在initialize方法中根据参数中获得的类名,创建加载显示类,初始化显示类的基本属性,并把自己赋值给加载显示类的preloader属性。
加载显示类必须实现IPreloaderDisplay接口,这是Preloader类的要求,因为Preloader正是把加载显示类的实例强制转化为IPreloaderDisplay接口来进行访问的。通过IPreloaderDisplay接口的方法,Preloader才能够完成对加载显示类的基本属性的设置。这些属性包括backgroundImage和backgroundSize等,后面还会对IPreloaderDisplay接口详细介绍。
有时候我们认为默认的加载显示类不能满足要求,希望实现更有特色的进度显示。我们可以通过三种方法改变加载显示类的表现形式:第一,修改默认显示类进度条的属性;第二,监听加载进程事件,重新绘图;第三,重新实现IPreloaderDisplay接口。这三种方法需要重新编写代码的工作量依次增加,当然,展现方式的自由度也依次增加了。
你也许会想,是否可以使用标记来修改进度条的属性呢?首先,没有提供修改进度条的属性;其次,我们已经知道,preloader发生在第一帧,而Application和所有组件都是在第二帧初始化的。因此,即便能够使用标记来修改进度条属性,那也是在第一帧的工作做完之后,而这时进度条已经不再显示了。所以,要想修改默认的Preloader显示类的行为,只能够通过修改代码来完成。下面我们依次介绍改变预加载默认显示的三种方法。
1. 修改进度条的属性
预加载的默认显示类是DownloadProgressBar(下载进度条),要修改下载进度条的显示形式,就要从默认的DownloadProgressBar继承,然后修改其属性值,覆写该类的方法,最后将新的实现类指定给application的preloader属性,从而实现不同风格的下载进度条。新建一个ActionScript类,从DownloadProgressBar继承,属性修改代码如代码清单3-1所示。
代码清单3-1 修改进度条的属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | import flash.geom.Rectangle; import flash.text.TextFormat; import mx.graphics.RoundedRectangle; import mx.preloaders.DownloadProgressBar; public class MyDownProBar extends DownloadProgressBar { [Embed(source= "bcgImage.jpg" )] //进度条的背景图片 [Bindable] private var bcgImageClass: Class; public function MyDownProBar() { super(); downloadingLabel= "下载中..." ; //默认为 Loading initializingLabel= "初始化中..." //默认为 Initializing showLabel= true ; //是否显示标签,默认为true showPercentage= true ; //是否显示下载百分比,默认为true } override public function get backgroundImage():Object{ return bcgImageClass; //背景图片 } override public function get backgroundSize():String{ return "30%" ; //背景的尺寸,背景默认的尺寸是充满整个舞台的 } override public function get backgroundAlpha():Number{ return 0.5; //控件相对于背景的透明度 } //override public function get backgroundColor():uint //{ // return 0x00FF00; //背景颜色,设置背景颜色或图片只能选其一 //} //进度条边沿框的矩形区域(使进度条看起来是凹进去的) override protected function get barFrameRect():RoundedRectangle{ return new RoundedRectangle(14, 40, 154, 10); } //进度条的矩形区域 override protected function get barRect():RoundedRectangle { return new RoundedRectangle(14, 39, 154, 12, 0); } //外围边框的矩形区域(使进度条看起来在一个panel里) override protected function get borderRect():RoundedRectangle { return new RoundedRectangle(0, 0, 182, 60, 10); } //label 的显示格式 override protected function get labelFormat():TextFormat { var tf:TextFormat = new TextFormat(); tf.color = 0x333333; tf.font = "Verdana" ; tf.size = 12; return tf; } //显示label的矩形区域 override protected function get labelRect():Rectangle{ return new Rectangle(14, 17, 100, 18); } //百分比的文字格式 override protected function get percentFormat():TextFormat{ var tf:TextFormat = new TextFormat(); tf.align = "right" ; tf.color = 0x000000; tf.font = "Verdana" ; tf.size = 12; return tf; } //显示百分比的矩形区域 override protected function get percentRect():Rectangle{ return new Rectangle(108, 4, 34, 16); } } |
代码清单3-1中列出了可以修改的属性和可以覆写的方法,代码只是对部分属性的值做了修改,包括提示的字体以及进度条的高度。
注意 虽然backgroundImage、backgroundSize、backgroundAlpha以及backgroundColor都是public的属性,但是通过直接赋值的方法并不能起到作用,必须覆盖其get方法才能起作用。
背景图片(backgroundImage)和背景颜色(backgroundColor)这两个属性不能同时设置,只能选其一。这两个属性的默认作用范围是舞台(stage)的大小,可以通过覆写backgroundSize的get方法来控制背景图片和背景颜色的大小(相对于舞台的一个比例)。背景透明度(backgroundAlpha)是指进度条相对于背景的透明度,也必须通过覆写get方法来修改。
注意,虽然Application也具有与上述相同的属性,但是DownloadProgressBar的上述属性是在第一帧显示的属性,而Application的上述属性是控制第二帧的显示。
在Application标记中添加属性preloader=“flex.sample.MyDownProBar”,编译运行Application,能看到修改后的进度条效果如图3-1所示,与默认的进度条(如图3-2所示)比较可以看出修改后的效果。
通过上述方法能够修改进度条的边框、背景图片、下载提示标签文本、初始提示标签文本,以及是否显示百分比等。但是,进度条的整体框架形式无法改变。如果想制作其他形式的进度条,需要采用另外两种方式。
2. 监听加载进程事件并重新绘图
为了能够实现自己绘图,必须要能够处理加载进程的相关事件,包括下载进程事件、下载完毕事件、初始化开始事件和初始化结束事件等。这些事件都是由preloader对象发送的,DownloadProgressBar类在设置自身的preloader属性时对这些事件进行监听。因此,为了能够实现自行绘制进度条,就需要覆写DownloadProgressBar的preloader属性的set方法。具体实现如代码清单3-2所示。
代码清单3-2 监听加载进程事件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | import flash.display.Graphics; import flash.display.Sprite; import flash.events.*; import flash.text.TextField; import mx.containers.Canvas; import mx.events.*; import mx.preloaders.DownloadProgressBar; public class MyDownProBar extends DownloadProgressBar { private var progressBar:Sprite; private var myLabel:TextField public function MyDownProBar(){ super(); myLabel= new TextField(); //创建显示信息的文本标签 myLabel.x=200; myLabel.y=200; addChild(myLabel); } //覆盖DownloadProgressBar方法,监听相关事件 override public function set preloader(s:Sprite): void { s.addEventListener(ProgressEvent.PROGRESS,inProgress); s.addEventListener(Event.COMPLETE,complete); s.addEventListener(FlexEvent.INIT_COMPLETE,initComplete); s.addEventListener(FlexEvent.INIT_PROGRESS,initProgress); } //进程中自行绘图 private function inProgress(e:ProgressEvent): void { var barWidth:Number = e.bytesLoaded/e.bytesTotal*100; var g:Graphics = this .graphics; //绘图区域 g.clear(); g.beginFill(0x88ff22); g.drawRect(180,220, 100, 20); g.endFill(); g.beginFill(0xff9900); g.drawRect(180,220, barWidth, 20); g.endFill(); myLabel.text=String( int (barWidth))+ " %" ; } private function complete(e:Event): void { myLabel.text= "下载完毕" ; } private function initComplete(e:FlexEvent): void { myLabel.text= "初始化完毕" //初始完后要派发 Complete 事件,不然不会进入第二帧 dispatchEvent( new Event(Event.COMPLETE)); } private function initProgress(e:FlexEvent): void { myLabel.text= "初始化..." ; //进度条开始加载的方法 } } |
上述代码的实现效果,如图3-3所示。
实现的效果还是比较简陋的,毕竟关于绘图方面的代码很简单,要想实现赏心悦目的进度条,需要更多的绘图代码。
3. 重新实现IPreloaderDisplay接口
从Sprite类继承,实现IpreloaderDisplay接口,相当于重新开发一个DownloadProgressBar。由于篇幅所限,本书不详细讨论实现细节,只对实现的原理稍作讲解。首先,我们看一下IPreloaderDisplay要求实现的方法,如代码清单3-3所示。
代码清单3-3 IPreloaderDisplay接口
1 2 3 4 5 6 7 8 9 10 11 | public interface IPreloaderDisplay extends IEventDispatcher { function get backgroundAlpha():Number; function set backgroundAlpha(value:Number): void ; function get backgroundColor(): uint ; function set backgroundColor(value: uint ): void ; function get backgroundImage():Object; function set backgroundImage(value:Object): void ; function get backgroundSize():String; function set backgroundSize(value:String): void ; function get stageHeight():Number; //舞台高度 |
1 2 | function set stageHeight(value:Number): void ; function get stageWidth():Number; //舞台宽度 |
1 2 3 4 | function set stageWidth(value:Number): void ; function set preloader(obj:Sprite): void ; function initialize(): void ; //进度条创 建后的初始化方法,配置进度条属性 } |
可以看到,代码中设置属性的方法就是我们在第一种实现方式中设置的属性,方法的实现可以参考代码清单3-1中的代码。而接口中preloader的set方法的实现和第二种实现方式中的preloader的set方法的内容是基本一致的。通过监听下载和初始化事件,通过绘图实现自己的Preloader。通过实现接口,可以更加自由地修改进度条的展示方式。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?