About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Jan

    26

    Feathers3 DateTimeSpinner 一些备注

    • 0 Comments
    • Flash Platform

    DateTimeSpinner 是一组 SpinnerList 组成的组件,用来选择日期和时间。它支持多种编辑模式,允许用户只选择日期,只选择时间,或两者。

    var spinner:DateTimeSpinner = new DateTimeSpinner();
    spinner.editingMode = DateTimeMode.DATE;//设置显示日期、时间或同时显示
    spinner.minimum = new Date(197001);
    spinner.maximum = new Date(20501131);
    spinner.value = new Date(20151031);
    this.addChild( spinner );

    DateTimeSpinner 对象的 value 属性值代表当前选择的日期与时间值。minimum 与 maximum 属性值决定一个被选择日期与时间的范围(minimum 与 maximum 属性也可以省略设置,会自动选择一个合理的范围)。

    与其它大多数组件一样,设置皮肤外观两种方式,一种是通过主题文件(theme),另一种是没有主题文件(或不通过主题文件):

    通过主题文件设置样例代码: 

    getStyleProviderForClass( SpinnerList )
        .setFunctionForStyleName( DateTimeSpinner.DEFAULT_CHILD_STYLE_NAME_LIST, setDateTimeSpinnerListStyles );

    private function setDateTimeSpinnerListStyles( list:SpinnerList ):void
    {
        var skin:Image = new Image( texture );
        skin.scale9Grid = new Rectangle( 2316 );
        list.backgroundSkin = skin;
    }

    也可以在主题文件中自定义样式名称:

    spinner.customListStyleName = "custom-list";

    //通过 customListStyleName 样式属性名称设置
    getStyleProviderForClass( SpinnerList )
        .setFunctionForStyleName( "custom-list", setDateTimeSpinnerCustomListStyles );

    不通过主题文件设置皮肤外观,而是通过 listFactory 属性设置子组件的外观:

    spinner.listFactory = function():SpinnerList
    {
        var list:SpinnerList = new SpinnerList();

        //skin the lists here, if you're not using a theme
        var skin:Image = new Image( texture );
        skin.scale9Grid = new Rectangle( 2316 );
        list.backgroundSkin = skin;

        return list;
    }

    Jan

    25

    Feathers3 SpinnerList 一些备注

    • 0 Comments
    • Flash Platform

    SpinnerList 类是 List 类的子类,一个 SpinnerList 通常在用户进行滚动时会被设为无限循环,被选择项位于列表的中间,在视觉上用突出的颜色表示。

    SpinnerList 与常规的 List 类稍稍有些不同的地方,就是不能将 isSelectable 设为 false,否则就会抛出异常。因为 SpinnerList 使用的意图就是为了选择某一项。

    选择项在视觉上的高亮皮肤可以自定义,可以是任何 Starling 显示对象,如 starling.display.Image:

    list.selectionOverlaySkin = new Image( texture );

    皮肤是水平居中或垂直居中取决于滚动的方式。

    Jan

    25

    FlowLayout 用于显示从左向右的多行显示布局(如 List、LayoutGroup、ScrollContainer 等),支持水平或垂直分页,有许多简单的属性支持间距、对齐等设置。

    a、常用的简单属性如:padding、paddingTop、paddingRight、paddingBottom、paddingLeft、gap、horizontalGap、verticalGap、horizontalAlign、verticalAlign、 rowVerticalAlign 等等。

    b、支持虚拟化布局(关于虚拟化布局的备注资料参看《Feathers3 HorizontalLayout & VerticalLayout 一些备注》第3条)。

    WaterfallLayout 与上面的 FlowLayout 类似,但它是显示多个列的布局,每一项的宽度是相同的,高度可以不同。所有项会按顺序被添加到布局,但每一项可能会被添加到任何可用的一列中(布局标准为:在布局进行时被选择的列高度,再加上被添加项的高度产生的列高度尽可能的小)。

    a、常用的简单布局属性基本上与上面的 FlowLayout 类列举的类似。

    b、还可以通过 requestedColumnCount 属性指定请求布局的列数(容器的尺寸可能会比较小,请求的列数如果过多的话会无法按请求的列数布局,只会按最大可容纳的数量列数布局;但只要容器的尺寸足够大,就会按请求的列数进行布局)。如果容器没有手动指定容器的宽度,设置requestedColumnCount 属性值后,会按请求自动计算出容器的宽度。

    c、同样支持虚拟化布局。

    Jan

    25

    媒体播放器控件(Media player controls)用于控制媒体播放器,如播放、暂停、全屏、静音、播放头进度时间提示等等,在 Feathers 中的控件罗列:

    1、FullScreenToggleButton:用于控制切换视频播放器(VideoPlayer)全屏状态。

    2、MuteToggleButton:控制媒体播放器是否静音。

    3、PlayPauseToggleButton:控制播放与暂停。

    4、SeekSlider:控制播放头位置、进度提示。

    5、TimeLabel:显示当前时间、剩余时间或总时间。

    6、VolumeSlider:控制音量大小。

    Jan

    25

    Feathers3 VideoPlayer 一些备注

    • 0 Comments
    • Flash Platform

    VideoPlayer  通过 flash.net.NetStream 对象提供视频播放功能。视频文件可以是一个  URL 地址来源,并作为 Starling 纹理显示。媒体播放器控件(Media player controls)可以作为视觉元素 / 控件添加到 VideoPlayer 对象中,比如播放、暂停、当前的时间进度等元素。VideoPlayer 类是 LayoutGroup 类的子类,所以子元素可以通过布局对象进行布局。

    最基本的流程:

    var player:VideoPlayer = new VideoPlayer();
    player.setSize( 320300 );//设置尺寸
    this.addChild( player );//添加到显示列表
    player.videoSource = http://example.com/video.m4v;

    视频中的每一帧画面会成为 Starling 中的纹理对象,所以我们使用 ImageLoader 对象来显示纹理:

    //添加一个 ImageLoader 对象作为 VideoPlayer 的子对象用于显示视频纹理
    var loader:ImageLoader = new ImageLoader();
    player.addChild( loader );

    此时还没有设置 ImageLoader 的 source 属性。在 GPU 上需要一些时间初始化视频纹理用于 Starling 的渲染,一旦可以将纹理传递给 ImageLoader,VideoPlayer 对象就会调度 Event.READY 事件(在 Event.READY 事件派发之前,VideoPlayer 对象的 texture 属性值是 null)。

    function videoPlayer_readyHandler( event:Event ):void
    {
        loader.source = player.texture;//视频纹理可以通过 texture 属性访问
    }
    player.addEventListener( Event.READY, videoPlayer_readyHandler );

    同时还需要侦听 Event.CLEAR 事件,当视频纹理被销毁时将会派发此事件:

    function videoPlayer_clearHandler( event:Event ):void
    {
        loader.source = null;
    }
    player.addEventListener( Event.CLEAR, videoPlayer_clearHandler );

    添加一些视觉元件控件可以用于控制视频的播放:

    var controls:LayoutGroup = new LayoutGroup();
    controls.styleNameList.add( LayoutGroup.ALTERNATE_STYLE_NAME_TOOLBAR );//作为一个 toolbar 添加
    player.addChild(controls);

    var button:PlayPauseToggleButton = new PlayPauseToggleButton();
    controls.addChild( button );

    var slider:SeekSlider = new SeekSlider();
    controls.addChild( slider );

    这两个控件都是 Feathers 提供的内置的“媒体播放器控件”,不需要为它们编写任何业务逻辑代码就能控制视频的播放。

    视频加载的几种方式:

    a、如上面的网络 URL 地址:

    player.videoSource = http://example.com/video.mp4;

    b、本地文件地址(本质上它还是一个 URL 地址):

    var videoFile:File = File.applicationDirectory.resolvePath("video.mp4");
    player.videoSource = videoFile.url;//这里一定要记得使用 url 属性,如使用 nativePath 不会起作用的

    c、从流媒体服务器加载,类似商业的 Adobe Media Server 或开源的 Red5 Media Server ,通过 netConnectionFactory 属性连接服务器,然后在 videoSource 属性设置视频流的名称:

    player.netConnectionFactory = function():NetConnection
    {
        var nc:NetConnection = new NetConnection();
        nc.connect("rtmp://localhost/vod");
        return nc;
    };
    player.videoSource = "mp4:streams/myvideo";

    如果是同一个服务器上不同的视频流,只需要更改 videoSource 属性的视频流的名称就可以。

    Jan

    25

    Feathers3 SoundPlayer 一些备注

    • 0 Comments
    • Flash Platform

    SoundPlayer 支持 URL 加载或从一个 Sound 对象加载,媒体播放器控件(Media player controls)可以作为视觉元素 / 控件添加到 SoundPlayer 对象中,比如播放、暂停、当前的时间进度等元素。SoundPlayer 类是 LayoutGroup 类的子类,所以子元素可以通过布局对象进行布局。

    最基本用法的样例代码:

    var player:SoundPlayer = new SoundPlayer();
    this.addChild( player );//如果不想添加视觉元件,也可以不添加到显示列表
    player.soundSource = http://example.com/sound.mp3;

    比如,添加一些视觉元素控件可以用于控制音频的播放:

    var button:PlayPauseToggleButton = new PlayPauseToggleButton();//添加一个暂停按钮
    player.addChild( button );

    var slider:SeekSlider = new SeekSlider();//添加一个播放头控制控件
    player.addChild( slider );

    这两个控件都是 Feathers 提供的内置的“媒体播放器控件”,不需要为它们编写任何业务逻辑代码就能控制音频的播放。

    如上样例,SoundPlayer 类结合了媒体播放器控件后,无论是播放音频还是控制音频都变的十分方便。

    Jan

    22

    自定义项渲染器(custom item renderers)一般是通过扩展现成的 Feathers LayoutGroup 子类实现的,或者自行实现对应的接口(实际上就是创建自定义的 Feathers 组件并实现指定的接口类型)。

    扩展现成的 LayoutGroup 子类一般是指扩展以下三个类:

    LayoutGroupListItemRenderer 作为 List 的项渲染器
    LayoutGroupGroupedListItemRenderer 作为 GroupedList 的项渲染器
    LayoutGroupGroupedListHeaderOrFooterRenderer 为作 GroupedList 的 header 或 footer 项渲染器

    扩展这些子类创建自定义的渲染器好处就是已经实现了必要接口所需要的业务逻辑并进行了优化,一些基础功能和常用的方法都被提供了(比如data、index、owner 属性等)。坏处就是它有可能会稍稍的降低一些性能(个人觉的可以忽略不计)。

    实现对应的接口一般指扩展 FeathersControl 这个抽象的基类,并实现 IListItemRenderer、IGroupedListItemRenderer、IGroupedListHeaderOrFooterItemRenderer 这三个接口(因为一般都是通过扩展 LayoutGroup 子类可以方便的实现自定义项渲染器,所以实现接口不是我要备注的资料,以下就省略了)。

    一般流程如下(如果熟悉 Flex 的话估计也会很熟悉):

    1、CustomItemRendererClass 类扩展某个 LayoutGroupXXXXXXRenderer 类,然后通过 itemRendererFactory 或 itemRendererFactory 来赋值提供给列表使用。

    通过列表类组件的 itemRendererFactory 属性可以设置 List 的对象的自定义的项渲染器,如:

    list.itemRendererType = CustomItemRendererClass;

    也可以通过列表类组件的 itemRendererFactory 属性设置,如:

    list.itemRendererFactory = function():IListItemRenderer
    {
        var renderer:CustomItemRendererClass = new CustomItemRendererClass();
        return renderer;
    };

    2、编写 CustomItemRendererClass 类的具体业务逻辑代码,如在生命周期的资料中备注的,推荐覆盖 initialize() 方法,添加子对象、侦听器(这些侦听器一般是不打算移除的,直到渲染器被 disposed() 方法调用销毁)、使用布局类对象进行布局等初始化相关的代码,而不是放在构造函数中。

    也有一些例外,比如将一些事件侦听器添加在 FeathersEventType.RENDERER_ADD 的侦听器中,一般很少用这种(可能偶尔会在大数据并结构虚拟化布局时可能会用到),最终确保在 FeathersEventType.RENDERER_REMOVE 的侦听器中移除对应的事件侦听器。

    3、解析 data 对象,简单的覆盖 commitData() 方法(比如项渲染器中有一个 Label 组件):

    override protected function commitData():void
    {
        if(this._data)
        {
            this._label.text = this._data.label;
        }
        else
        {
            this._label.text = null;//不要忘了设为 null 避免运行时产生错误
        }
    }

    4、如果要添加其它属性,就使用 setter 方法,最后需要用 invalidate() 方法失之失效再重新验证(其它的样式布局相关的操作都如同在 LayoutGroup 中一样):

    protected var _padding:Number = 0;

    public function get padding():Number
    {
        return this._padding;
    }

    public function set padding(value:Number):void
    {
        if(this._padding == value)
        {
            return;
        }
        this._padding = value;
        this.invalidate(INVALIDATION_FLAG_LAYOUT);
    }

    5、覆盖 preLayout() 方法,用于更新子对象的布局属性(发生在项渲染器的 layout 代码运行之前,还可以覆盖 postLayout() 方法,它发生在项渲染器的 layout 代码运行之后,一般不会用到它)。

    一份简单而完整的自定义项渲染器代码样例:

    ……

    在 “Feathers Cookbook” 还有许多现成的关于自定义项渲染器的片段代码样例:

    a、自定义项渲染器添加背景皮肤

    b、处理触摸状态

    c、通过点击或触屏选择一个自定义项渲器

    d、当一个自定义项渲染器被触碰时防止列表滚动

    e、派发一个“开关”事件

    f、派发一个长按事件

    More...

    Jan

    22

    Feathers3 “组件生命周期(Feathers Component Lifecycle)”经历以下几个过程:

    1、实例化(Instantiation)

    通过关键字 new 生成对象,此时组件还没有被添加到显示列表上,可以任意修改属性,此时组件不会进行任何渲染,直到它被添加到显示列表中才会对显示相关的属性作出反应。有一个宗旨就是尽量减少在构造函数中初始化相关的代码量(除非是没有被添加到显示列表前,就需要确定的初始化相关的代码才 需要在构造函数中完成),初始化相关的代码尽量放在下面介绍的 initialize() 方法中。

    2、初始化(Initialization)

    组件被添加到显示列表后,initialize() 方法被自动调用,这个方法只会在组件第一次被添加到显示列表时被调用(只会被调用一次,如果将它从显示列表移除,再重新添加也兴地再次运行),开发者可以覆盖这个方法进行子对象相关的布局,其它初始化相关的代码也要尽量放在这个方法体内,尽量减少构造函数中初始化相关的代码。这个方法体内的所有代码执行结束后,会派发一个 FeathersEventType.INITIALIZE 事件,表示初始化方法 initialize() 执行结束了。

    如果一个组件在被添加到显示列表前调用了 validate() 方法,那么 initialize() 方法会被立即执行(请注意:FeathersEventType.INITIALIZE 与 FeathersEventType.CREATION_COMPLETE 事件也会被派发;后续的操作再将这个组件添加到显示列表时就不会再执行 initialize() 方法,也不会再派发这些事件了)。

    3、应用主题样式(Apply theme styles)

    一般来说,使用 Feathers 进行开发的时候,都会有一个主题文件(theme,也不排除一些开发者会直接在业务逻辑相关的类中直接进行皮肤样式的设置而不使用主题文件,但这是不推荐的),在 FeathersEventType.INITIALIZE 事件派发后,会立即应用主题文件的样式属性设置到组件上(如果没有主题文件, 此过程就被跳过了)。

    4、验证(Validation)

    组件进入第一次验证阶段,此时组件的所有属性就好像都已失效(关于失效,查看下面的 Invalidation 过程介绍),会进行一次完成的属性处理。当第一次验证结束后,会派发一个 FeathersEventType.CREATION_COMPLETE 事件(也就是在第一次 draw() 方法后会派发这个事件)。

    当进行验证操作的时候,组件会调用 draw() 方法,任何组件已更改的属性会在 draw() 方法中进行处理。如果对组件没有进行手动坐标、尺寸设置,组件需要根据预置配置相关的数据,自动计算用于布局的尺寸(包括最小值),用于预置自动计算相关的值机会被传递给 saveMeasurements() 方法,计算出最终布局尺寸。组件根据需要调整子对象的坐标与尺寸等。

    a、请注意:这里的 draw() 并不是真正的渲染对象,而只是表示对绘制时的数据处理,决定需要重绘的属性,真正的绘制过程是下面的 render() 方法对应的渲染过程。

    b、在创建自定义组件的时候,draw() 方法既简单,又有用,通过它就能完成验证步骤。

    c、在 draw() 方法中,调用 isInvalid() 方法可以判断某个属性是否失效的,是否需要重绘的(如果调用 isInvalid() 方法时没有传入失效类型参数,那么任意的一个失效标志(flags)都会返回 true)。

    d、如果没有手动设置组件的宽与高,在验证步骤中,saveMeasurements() 方法就会被调用,根据子组件、皮肤、样式布局等设置,来自动计算组件的尺寸。

    e、isQuickHitAreaEnabled 属性它有点类似于传统显示对象中的 mouseChildren 属性,它可以大大提高点击碰撞测试的性能(touch hit tests),如果子组件不需要碰撞检测,可以用它来优化性能。它会将碰撞检测简化为对一个 actualWidth 与 actualHeight 的矩形(自动计算出来的)碰撞检测。

    f、Feathers 组件 width 与 height 属性的设置与读取取决于多个因素,这两个值在通过 setter 方法设置时内部对应的是私有的 _explicitWidth 与 _explicitHeight 属性值,当手动设置的时候,就会更改 _explicitWidth 与 _explicitHeight 属性,再通过 getters 方法返回的也就是对应的 _explicitWidth 与 _explicitHeight 属性值;只读属性 explicitWidth 与 explicitHeight 也会暴露“ _explicit”私有值,explicitWidth 与 explicitHeight 两个值也是用于布局的值。如果没有手动设置 width 与 height 属性,那么就会被自动计算出来,最终结果会被传递给 saveMeasurements() 方法。

    5、渲染(Render)

    Feathers 显示相关的组件都是 Starling 显示对象,所以它有一个 render() 方法,Starling 会在每一帧调用这个方法(Feathers 组件通常不会覆盖 Starling 的 render() 方法),在组件 render()方法被调用前,总是会执行验证步骤。

    6、失效 (Invalidation)

    接下来,当组件的属性出现变化时,组件需要将对应属性失效的类型参数(一个或多个)传递给 invalidate() 方法,通常它在一个 setter 方法体内,失效的类型参数可以是代表尺寸、布局、选择状态的等等。每个组件可能会有一些自己独特的失效类型参数,但一些常用的失效类型参数已经作为常量被定义在 FeathersControl 这个基类上了。失效类型参数如何使用没有任何强制规则,可以随意调用 invalidate() 方法不传入任何参数。

    在组件“失效”后,组件就会进入等待“验证”的步骤(此时也可以手动强制执行 validate() 方法进入验证步骤,比如想立即得到组件的宽与高值,这些值是在验证步骤中计算的) ,在到达渲染步骤前,属性可能再次发生改变或其它属性也可能发生改变。当组件进入渲染步骤的时候,会确保所有属性更改已提交(committed)到渲染的需求。

    失效→验证→渲染,这个循环的过程会一直进行,直到组件从显示列表被移除,它才会停止;如果再次被添加到显示列表,这个过程就会又继续。

    7、移除 (Removal)

    组件从显示列表被移除后,就不会再自动进入验证步骤,所有属性的更改会被保存,但不会再被提交(committed)到渲染的需求里。除非它再次被添加到显示列表,才会重新开始进入验证步骤。如果组件不在显示列表上(不在舞台上),也想让组件也进入“验证”步骤,需要手动调用组件的 validate() 方法。

    8、销毁(Disposal)

    与 Starling 显示对象一样,Feathers 的组件也有 dispose() 方法,用来移除事件侦听器、纹理、子对象等。一个组件被销毁后自然就不能再进行验证了。被调用 dispose() 方法不应该是被添加在显示列表上的对象(需要先将它从显示列表移除),否则就可能产生运行时异常或失去所有响应。

    9、垃圾回收(Garbage Collection)

    当组件的所有引用被去除的时候,它就适合被垃圾回收器回收了(垃圾回收器的回收工作是不可控制的)。

    Jan

    19

    DefaultListItemRenderer 与 DefaultGroupedListItemRenderer 分别是 List 与 GroupedList 默认的项渲染器,在定义列表类组件的外观样式时,它们是主要操作的目标,因为它们扩展自同一个类,所以基本功能与用法都相似(“幕后”代码有不同的地方不用管,毕竟名称不一样么 - -!!),直接用 DefaultListItemRenderer 指代两者了。

    默认项渲染器 DefaultListItemRenderer 除了能显示文字、 icon 外,甚至还能添加额外的显示对象,也包括提供了其它一些常用的方法,比如 labelFactory() 方法可以用于动态格式化 / 处理文本内容。

    a、DefaultListItemRenderer 的常用字段是 labelField、iconSourceField,如下代码:

    var groceryList:ListCollection = new ListCollection(
        [
            { text: "Milk", thumbnail: textureAtlas.getTexture( "milk" ) },
            { text: "Eggs", thumbnail: textureAtlas.getTexture( "eggs" ) },
            { text: "Bread", thumbnail: textureAtlas.getTexture( "bread" ) },
            { text: "Chicken", thumbnail: textureAtlas.getTexture( "chicken" ) },
        ]);
    list.dataProvider = groceryList;

    list.itemRendererProperties.labelField = "text";
    list.itemRendererProperties.iconSourceField = "thumbnail";

    DefaultListItemRenderer 对应字段的对象都是动态创建的,比如上面 labelField 字段对应创建了一个文本渲染器组件,iconSourceField 字段对应的创建了一个 ImageLoader 对象。如果不设置 iconSourceField 字段的值,DefaultListItemRenderer 不会动态的创建 ImageLoader ,这样使的性能大大提高了。

    因为 DefaultListItemRenderer 的 iconSourceField 创建的是一个 ImageLoader 对象,实际上也可以直接给它符值为 URL 字符串,它会提供给 ImageLoader  的 source 属性。

    b、DefaultListItemRenderer 还包含了不常用的字段 accessoryField ,能把其它显示对象作为子对象显示(包括 Starling 对象),这种 accessory 显示对象在列表中可以与用户单独交互的(不同于 icon 默认是没有效互能力的),如果有 accessory 显示对象,最好关闭列表的 isSelectable 功能。

    c、还有一些不常用的如 accessoryLabelField、iconLabelField 等是一些文本渲染器对象。

    d、iconField 字段可以显示 Feathers 或 Starling 对象,如下代码:

    var slider:Slider = new Slider();
    //对 Slider 对象进行属性设置,用于下面的control 字段
    list.dataProvider = new ListCollection(
    [
        { label: "Example Label", control: slider }
    ];
    //此时项渲染器在 icon 位置创建的就是 Slider 对象
    renderer.iconField = "control";

     这里需要记住的是当项渲染器或 list 对象被销毁(disposed)的时候,它是不会自动被销毁的。如果确定对象不需要了,需要手动销毁它(无论是通过 data 或 ListCollection 对象),防止内存泄漏。

    可以不通过数据提供者修改数据,直接对 icon 进行皮肤设置,比如当项渲染器被选中的时候, icon 会作出外观上的改变(此时数据并没有变化),设置 itemHasIcon 为 false,然后通过 defaultIcon 属性和 setIconForState() 方法像设置普通按钮一样进行设置。

    e、DefaultListItemRenderer 中还可以显示一个额外(accessory)的显示对象,是直接作为可交互的子对象添加的(不同于 icon 对象默认没有交互功能),所以最好将列表组件的 isSelectable 功能关闭,避免用户在操作时有冲突产生。

    1、accessorySourceField、accessoryLabelField 是为了开发时灵活与方便性存在的,额外的显示纹理图或文本。

    2、accessoryField 和前面使用 iconField 一样,可以显示任何 Starling 显示对象,但这种子对象不会自动随着 List 与项渲染器的销毁而销毁,同样需要手动销毁。

    3、也可以将额外的显示对象变成不可交互的类似 icon 的部件,itemHasAccessory 设为 false,通过 defaultAccessory 属性和 setAccessoryForState() 方法进行设置。

    DefaultListItemRenderer 类其实是一个 ToggleButton 类的子类,所以 ToggleButton 上能用的样式与功能,在 DefaultListItemRenderer 类上基本上都能用。

    Jan

    19

    Feathers3 GroupedList 一些备注

    • 0 Comments
    • Flash Platform

    GroupedList 的数据源是通过 HierarchicalCollection 包装的,虽然官方的帮助资料中写了可以包装任何类型的数据,但实际上“即时”可用的只有 Array 类型(在 IHierarchicalCollectionDataDescriptor 帮助页面中实现的类只有 ArrayChildrenHierarchicalCollectionDataDescriptor)。

    每个数组元素对象需要类包含 children 字段(也可以自定义字段,还可以包含其它字段如 header、footer,但其它字段后面需要手动指定给对应的属性),类似如下结构:

    var groceryList:HierarchicalCollection = new HierarchicalCollection(
    [
        {
            header: { text: "Dairy" },
            children:
            [
                { text: "Milk", thumbnail: textureAtlas.getTexture( "milk" ) },
                { text: "Cheese", thumbnail: textureAtlas.getTexture( "cheese" ) },
            ]
        },
        {
            header: { text: "Bakery" },
            children:
            [
                { text: "Bread", thumbnail: textureAtlas.getTexture( "bread" ) },
            ]
        },
    ]);
    list.dataProvider = groceryList;

    如果要使用其它类型的数据比如 XMLList 作为被包装源对象,首先就要实现“IHierarchicalCollectionDataDescriptor”接口,然后再将实现类生成的对象先赋值给 HierarchicalCollection 对象的 dataDescriptor 属性,然后再将 HierarchicalCollection 对象赋值给 GroupedList 对象的 dataProvider。

    为 XML 数据类型报不平:AS3 是至目前为止,唯一一个严格遵守 ECMAScript4 标准的语言,AS3 也是至目前为止唯一一个实现 E4X 语法的语言,所有的 AS3 运行时环境都提供了 E4X 解析器,在许多 AS3 开发者手中却被白白的浪费了。操作 XML 数据是极其方便的,仅类似 SQL 语法的谓词过滤这一功能,就可以干死所有其它数据类型,不服你咬我啊?其它附属的特点也相当多,如层次结构清晰、索引功能、文本换行、通配符操作、命名空间、内置的注释、独立的属性等等一堆优势,而作者却没有给出可以即时使用的实现,元芳,你怎么看?……)。

    然后,将字段的名称赋值给对应的属性值,就可以显示 children 的项渲染器了(注意:这里没有任何指定 children 字段相关的操作,如果是其它字段就需要手动指定,如后面马上会看到的对 headr 字段的操作),

    list.itemRendererProperties.labelField = "text";
    list.itemRendererProperties.iconSourceField = "thumbnail";

    labelField、iconSourceField 基本上与 List 组件一样,这里先省略了,在整理 DefaultListItemRenderer 与 DefaultGroupedListItemRenderer 时再备注。

    header 字段相当于组名,footer 相当于对组的描述备注或者其它的一些附属的信息。它们一起使用 DefaultGroupedListHeaderOrFooterRenderer 类,可以用来显示文字,纹理图,或其它任何 Starling 显示对象。

    list.headerField = "header";

    不同于 children 字段,header 字段需要手动指定给属性。剩下的操作与 children 类似了。

    list.headerRendererProperties.contentLabelField = "text";

    header 与 footer 字段对应的对象可以稍稍简化一些,省去 contentLabelField 属性值的设置,它被使用的时候更像是对这个字段提供的对象调用了 toString() 方法:

    所以数组的元素被修改成这样也可以:

    {
        header: "Bakery",
        children:
        [
            { text: "Bread", thumbnail: textureAtlas.getTexture( "bread" ) },
        ]
    }

    程序化的选择项渲染器(数据源是被包装的类似“二维”的层次结构的对象,索引是从0开始的,所以下面的代码是选中第1组中第5个渲染器):

    list.setSelectedLocation(04);

    如果这里两个参数都传入 -1,那么表示取消选择。

    GroupedList 外观修改基本上和 List 一样,就是背景与布局,大多数情况下,开发者需要修改的实际上是项渲染器的外观。在整理外观主题、皮肤相关的资料时再备注。

    GroupedList 虚拟化布局、滚动条显示与滚动策略等基本上都跟 List 一致。

    GroupedList 与 List 不一样的地方,是每一组的第一个项渲染器(顶部圆角)、最后一个项渲染器(底部圆角),以及当组中仅有一个项渲染器(顶和底都是圆角)时可以分别进行不同的设置:

    firstItemRendererType
    firstItemRendererFactory
    lastItemRendererType
    lastItemRendererFactory
    singleItemRendererType
    singleItemRendererFactory

     这些属性的使用方法与 itemRendererType、itemRendererFactory都类似。

    header、footer 都有与 itemRendererType、itemRendererFactory类似的属性。

    不常用的一些功能,比如每一项的项渲染器有可能因为数据不同而不同,可以使用“多个项渲染器工厂”。