FLEX中Preloader预加载进度条

写此博客只为了方便自己查阅,如有侵权等请联系删除.

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 修改进度条的属性

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所示)比较可以看出修改后的效果。

通过上述方法能够修改进度条的边框、背景图片、下载提示标签文本、初始提示标签文本,以及是否显示百分比等。但是,进度条的整体框架形式无法改变。如果想制作其他形式的进度条,需要采用另外两种方式。

  1. 监听加载进程事件并重新绘图

为了能够实现自己绘图,必须要能够处理加载进程的相关事件,包括下载进程事件、下载完毕事件、初始化开始事件和初始化结束事件等。这些事件都是由 preloader对象发送的,DownloadProgressBar类在设置自身的preloader属性时对这些事件进行监听。因此,为了能够实现 自行绘制进度条,就需要覆写DownloadProgressBar的preloader属性的set方法。具体实现如代码清单3-2所示。

代码清单3-2 监听加载进程事件

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所示。

实现的效果还是比较简陋的,毕竟关于绘图方面的代码很简单,要想实现赏心悦目的进度条,需要更多的绘图代码。

  1. 重新实现IPreloaderDisplay接口

从Sprite类继承,实现IpreloaderDisplay接口,相当于重新开发一个DownloadProgressBar。由于篇幅所限, 本书不详细讨论实现细节,只对实现的原理稍作讲解。首先,我们看一下IPreloaderDisplay要求实现的方法,如代码清单3-3所示。

代码清单3-3 IPreloaderDisplay接口

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; //舞台高度
function set stageHeight(value:Number):void;
function get stageWidth():Number; //舞台宽度
function set stageWidth(value:Number):void;
function set preloader(obj:Sprite):void;
function initialize():void; //进度条创 建后的初始化方法,配置进度条属性
}
可以看到,代码中设置属性的方法就是我们在第一种实现方式中设置的属性,方法的实现可以参考代码清单3-1中的代码。而接口中preloader的 set方法的实现和第二种实现方式中的preloader的set方法的内容是基本一致的。通过监听下载和初始化事件,通过绘图实现自己的 Preloader。通过实现接口,可以更加自由地修改进度条的展示方式。

第二例子:

package com.iman.sps.sheet.ascript
{
import flash.display.Sprite;
import flash.display.;
import flash.events.
;
import flash.filters.BitmapFilterQuality;
import flash.filters.BlurFilter;
import flash.geom.Matrix;
import flash.net.;
import flash.text.TextField;
import flash.utils.
;
import flash.system.Capabilities;

import mx.events.*;  

import mx.preloaders.IPreloaderDisplay; 
 
public class MyProgressBar extends Sprite implements IPreloaderDisplay 
{ 
    [Embed(source="../image/logo.gif", mimeType="application/octet-stream")]  
    public var _loadingLogo:Class;  
     
    private var dpbImageControl:Loader;  
    private var _barSprite:Sprite;  
    private var progressText:TextField;         
    private var ProgressBarSpritIsAdded:Boolean = false;  

    public function MyProgressBar() 
    { 
        super(); 
    } 
     
    // Specify the event listeners.  
    public function set preloader(preloader:Sprite):void {  
        //Listen for 正在下载  
        preloader.addEventListener(ProgressEvent.PROGRESS, handleProgress);  
        //Listen for 下载完成  
        preloader.addEventListener(Event.COMPLETE, handleComplete);  
        //Listen for 正在初始化  
        preloader.addEventListener(FlexEvent.INIT_PROGRESS, handleInitProgress);  
        //Listen for 初始化完成  
        preloader.addEventListener(FlexEvent.INIT_COMPLETE, handleInitComplete);  
    }  
     
    // Initialize the Loader control in the override  
    // of IPreloaderDisplay.initialize().  
    public function initialize():void {  
        //添加logo图  
        dpbImageControl = new Loader();        
        dpbImageControl.contentLoaderInfo.addEventListener(Event.COMPLETE, loader_completeHandler);  
        dpbImageControl.loadBytes(new _loadingLogo() as ByteArray);  
        //dpbImageControl.load(new URLRequest("loadinglogo.swf"));  
    }  
     
     
    // After the SWF file loads, set the size of the Loader control.  
    private function loader_completeHandler(event:Event):void  
    {          
        addChild(dpbImageControl);  
        dpbImageControl.width = 136;  
        dpbImageControl.height= 54;  
        dpbImageControl.x = this.stage.stageWidth/2 - dpbImageControl.width/2;  
        dpbImageControl.y = this.stage.stageHeight/2 - dpbImageControl.height/2 - 40;  
    }    
     
    //  
    private function addProgressBarSprit():void{  
        //绘制背景渐变  
        var matrix:Matrix=new Matrix();  
        matrix.createGradientBox(this.stage.stageWidth,this.stage.stageHeight,Math.PI/2);  
        var colors:Array=[0x3399ff,0xFFFFFF];  
        var alphas:Array=[1,1];  
        var ratios:Array=[0,255];  
        this.graphics.lineStyle();  
        this.graphics.beginGradientFill(GradientType.LINEAR,colors,alphas,ratios,matrix);         
        this.graphics.drawRect(0,0,this.stage.stageWidth,this.stage.stageHeight);  
        this.graphics.endFill();  
         
        //绘制中心白色发光  
        var _Sprite1:Sprite = new Sprite();  
        addChild(_Sprite1);  
        _Sprite1.graphics.beginFill(0xffffff,0.45);  
        _Sprite1.graphics.drawEllipse(this.stage.stageWidth/2-130, this.stage.stageHeight/2-90, 280, 100);  
        _Sprite1.graphics.endFill();  
        //滤镜实现发光边缘柔和             
        var blur:BlurFilter = new BlurFilter();  
        blur.blurX = 100;  
        blur.blurY = 50;  
        blur.quality = BitmapFilterQuality.HIGH;  
        _Sprite1.filters = [blur];  
         
        //-------------------------------------------------  
         
        //绘制进度条背景  
        var _Sprite2:Sprite = new Sprite();  
        addChild(_Sprite2);  
        _Sprite2.graphics.lineStyle(1, 0xCCCCCC);  
        _Sprite2.graphics.beginFill(0xFFFFFF);  
        _Sprite2.graphics.drawRect((this.stage.stageWidth/2 - 152), (this.stage.stageHeight/2 - 10), 304, 20);    
        _Sprite2.graphics.endFill();  
         
        //-------------------------------------------------  
         
        //加载进度条Sprite  
        _barSprite = new Sprite();  
        addChild(_barSprite);  
        _barSprite.x = this.stage.stageWidth/2 - 150;  
        _barSprite.y = this.stage.stageHeight/2 - 8;  
         
        //-------------------------------------------------  
         
        //加载进度条文字  
        progressText = new TextField();  
        addChild(progressText);  
        progressText.textColor = 0x333333;  
        progressText.width = 300;  
        progressText.height = 18;  
        progressText.x = this.stage.stageWidth/2 - 152;  
        progressText.y = this.stage.stageHeight/2 + 20;  
    }  
     
    //刷新进度条  
    private function drawProgressBar(bytesLoaded:Number, bytesTotal:Number):void  
    {    
        if (_barSprite != null && progressText != null){  
            var g:Graphics = _barSprite.graphics;  
            g.clear();  
            g.beginFill(0xCCCCCC);  
            g.drawRect(0, 0, 300*(bytesLoaded/bytesTotal),16);    
            g.endFill();     
             
            var matrix:Matrix=new Matrix();  
            matrix.createGradientBox(300*(bytesLoaded/bytesTotal),16,Math.PI/2);  
            var colors:Array=[0x0099CC,0x99cc77];  
            var alphas:Array=[1,1];  
            var ratios:Array=[0,255];  
            g.lineStyle();  
            g.beginGradientFill(GradientType.LINEAR,colors,alphas,ratios,matrix);         
            g.drawRect(0,0,300*(bytesLoaded/bytesTotal),16);  
            g.endFill();   
             
             
        }  
    }  
     
    //正在下载的进度  
    private function handleProgress(event:ProgressEvent):void {  
        //第一次处理时绘制进度条Sprit  
        if (ProgressBarSpritIsAdded == false){  
            ProgressBarSpritIsAdded = true;  
            addProgressBarSprit();  
        }  
         
        if (progressText != null){  
            progressText.text = "下载进度:已下载 " + event.bytesLoaded + " byte,总大小 " + event.bytesTotal + " byte.";  
        }          
        drawProgressBar(event.bytesLoaded, event.bytesTotal);  
    }  
     
    private function handleComplete(event:Event):void {  
        if (progressText != null){  
            progressText.text = "下载完成.";  
        }  
        drawProgressBar(1,1);         
    }  
     
    private function handleInitProgress(event:Event):void {  
        if (progressText != null){  
            progressText.text = "正在初始化...";  
        }  
        drawProgressBar(1,1);  
    }  
     
    private function handleInitComplete(event:Event):void {  
        if (progressText != null){  
            progressText.text = "初始化完成.";  
        }  
        drawProgressBar(1,1);          
         
        //0.03秒后抛出完成事件  
        var timer:Timer = new Timer(300,1);  
        timer.addEventListener(TimerEvent.TIMER, dispatchComplete);  
        timer.start();       
    }  
     
    private function dispatchComplete(event:TimerEvent):void {  
        dispatchEvent(new Event(Event.COMPLETE));  
    }  

     
    public function get backgroundAlpha():Number 
    { 
        return 0; 
    } 
     
    public function set backgroundAlpha(value:Number):void 
    { 
    } 
     
    public function get backgroundColor():uint 
    { 
        return 0; 
    } 
     
    public function set backgroundColor(value:uint):void 
    { 
    } 
     
    public function get backgroundImage():Object 
    { 
        return null; 
    } 
     
    public function set backgroundImage(value:Object):void 
    { 
    } 
     
    public function get backgroundSize():String 
    { 
        return null; 
    } 
     
    public function set backgroundSize(value:String):void 
    { 
    } 
     
     
     
    public function get stageHeight():Number 
    { 
        return 0; 
    } 
     
    public function set stageHeight(value:Number):void 
    { 
    } 
     
    public function get stageWidth():Number 
    { 
        return 0; 
    } 
     
    public function set stageWidth(value:Number):void 
    { 
    } 
} 

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值