About

<#TEMPLATE_INCLUDE_NINEPAGE_ABOUTME#>
  • Jun

    24

    基本描述

    2K、4K 等高分辨率屏幕(也被称为“高分屏”)越来越普及,当小尺寸的高分屏出现时就需要用到缩放,一些 Adobe AIR 应用在高分屏中缩放后变模糊(不仅是旧有的 Adobe AIR 应用程序,好多原有的应用程序都出现了这种问题)。

    如:https://tracker.adobe.com/#/view/AIR-3975136

    解决方法

    升级 Adobe AIR SDK 到 22.0 以上的版本,并在应用的 -app.xml 描述文件的 initialWindow 标签内新增一个子标签:<requestedDisplayResolution>high</requestedDisplayResolution>(与 iPhone 设置 Retina 屏那个标签一样)。

    https://helpx.adobe.com/cn/flash-player/release-note/fp_22_air_22_release_notes.html

    此时 Stage.contentScaleFactor 属性就能正确反应缩放系数的值了。

    Apr

    19

    转载一个漂亮的 Flex4 Tooltips(其实我觉的它一点也不漂亮……好像就多了一个箭头么?):Flex4NiceTooltips.zip

    原文地址:http://www.hulstkamp.com/articles/flex-nicer-tooltips-and-balloon-help/srcview/index.html

    Apr

    19

    许多 Web 端与客户端程在上传文件时都会利用到 Flash AS3 技术,在 ADOBE 官方提供的《ADOBE ® ACTIONSCRIPT® 3.0 编程》手册中有一篇完整的官方示例教程:《Adobe ActionScript 3.0 示例:上载和下载文件》。

    Feb

    4

    现在的新版 本 Feathers 为了改善开发者的体验,已经大大简化了外观、子组件相关部份的 API,虽然下面的这些旧资料并不一定适用于新版本(是 Feathers 1.0 开始提供的),但很多资料信息依旧完全适用于新版本,所以一并整理下来备注了。

    首先不用说的一点就是 Feathers 强烈推荐使用主题文件,主题类可以集中设置皮肤相关的代码,便于将来的维护和更新,以及替换新的主题而不影响旧有的功能业务。主题的另外最大的好处就是能自动化给组件添加皮肤(既便是相同类型的组件提供不同的皮肤)。

    但 Feathers 也同时提供了不使用主题、或在主题文件外直接设置组件外观以及子组件的 API。关于新版本的皮肤备注资料,已在博客中单独提供了备注。下面也整理了旧版的 Feathers 资料中一些通用的与皮肤外观、子组件相关的资料。

    子组件工厂:

    子组件可以通过一个“工厂”设置皮肤,这里的“工厂”只是一种设计模式的叫法,跟其它什么“事件侦听器”、“样式提供程序”一样,其实就是个普通的函数在不同情况下叫法不一样。当一个组件需要子组件时调用这个函数,但这个函数不接受参数,却会返回一个子组件对象。下面看个工厂的例子,就是生成 Slider 组件的 thumb 子组件工厂:

    slider.thumbFactory = function():Button
    {
        var thumb:Button = new Button();
        thumb.defaultSkin = new Scale9Image( upTextures );
        thumb.downSkin = new Scale9Image( downTextures );
        return thumb;
    };

    如上代码中,函数创建了一个 Button 实例,在返回之前给它添加了一些皮肤。

    子组件的子组件:

    有些子组件会复杂一些,自身也会带有一些子组件,则可以为这些子组件单独提供工厂函数,以引用的方式一层一层的传递工厂函数。如下代码,给一个 List 组件设置滚动条的皮肤:

    function simpleScrollBarThumbFactory():Button
    {
        var thumb:Button = new Button();
        thumb.defaultSkin = new Scale3Image( thumbTextures );
        return thumb;
    }

    function simpleScrollBarFactory():SimpleScrollBar
    {
        var scrollBar:SimpleScrollBar = new SimpleScrollBar();
        scrollBar.thumbFactory = simpleScrollBarThumbFactory;
        return scrollBar;
    }

    list.verticalScrollBarFactory = simpleScrollBarFactory;

    如上代码,其实也可以将 simpleScrollBarThumbFactory() 函数以嵌套函数的方式放在 simpleScrollBarFactory() 函数内,但子组件过多时可能会不方便阅读代码。

    重复使用(并联)的工厂:

    如果组件已经设置了外观,并且想要继续对它的子组件进行其它属性设置,可以重复使用工厂,如下代码,已经在一个工厂方法中设置了 Panel 的 header 的外观,但还想进一步设置或修改它的 title 属性:

    var headerWithSkinsFactory:Function = panel.headerFactory;
    panel.headerFactory = function():Button
    {
        var header:Header = headerWithSkinsFactory();
        header.title = "Tools";
        return header;
    };

    开发者虽然可以在一个工厂中设置所有的外观以及所有的属性,但有时候仅仅只是想要在后期动态的修改它的 title 属性,这种方法就必不可少了。

    子组件属性:

    开发者也可以不使用工厂,而是通过父组件的“子组件属性”来“引用”子对象设置属性,所有设置的值会在下一次渲染时生效。这种方式性能略差一点,大多数情况下推荐使用工厂方法。但这种方式适用于在创建子组件后很久才调整属性和皮肤。以上面的 slider 为例:

    slider.thumbProperties.defaultSkin = new Scale9Image( upTextures );
    slider.thumbProperties.downSkin = new Scale9Image( downTextures );

    如上代码通过 thumbProperties 属性设置的皮肤,并不会立即将设置传递给子组件,而是要等到下一帧的渲染时才会传递给子组件。一般来说开发者不能通过这种方式去获取子对象的属性值,只应该使用这种方式来设置属性的值。thumbProperties 对象并不知道它存储数据的实际 Button 实例的任何内容。所以以下代码将产生错误,除非开发者自己实际设置了 isSelected:

    var isSelected:Boolean = slider.thumbProperties.isSelected;

    这段话的主要意思就是指 “thumbProperties ”只是一个存储数据的对象,这个子组件属性并不是真正的引用到了子组件,而只是给出了用于下一次渲染时提供给 thumb 按钮需要的数据,所以 thumbProperties 本身并不是 thumb 子组件。所以上面的黄色字“子组件属性”与“引用”打了引号,只是看起来好像是子组件的引用,但实际上只是给子组件提供需要的属性数据(由于在下一帧渲染时需要传递给某个子组件,所以对应的子组件是需要被先创建好的)。

    嵌套的子组件属性:

    如上面的 slider 的 thumbProperties “伪引用”了子组件,这种伪引用可以嵌套的,听起来好凌乱(- -!),所以一般都推荐使用工厂方法,但如果有需要的话也可以作为一种可选的方法用于实际开发。

    再次以 list 组件的滚动条为例,但这次不使用工厂,而是使用嵌套的“子组件属性”:

    list.verticalScrollBarProperties.@thumbProperties.defaultSkin = new Scale3Image( thumbTextures );

    注意在这里使用了属性运算符(@)。属性运算符告诉系统在另一个“子组件属性”对象内创建“子组件属性”对象,但前提是它尚不存在。 它不能用于常规属性,所以这就是为什么 defaultSkin 不以@开头。

    但使用这种语法有一个好处,可以避免覆盖可能已经存在的对象。如果使用一个全新的对象设置 thumbProperties,如下面这样的代码,它将替换整个应用程序中全部的 thumbProperties:

    //警告:这可能会覆盖的东西!
    list.verticalScrollBarProperties.thumbProperties =
    {
       defaultSkin: new Scale3Image( thumbTextures )
    };

    在这里就可以使用 @thumbProperties 并单独传递属性,以便不会删除 thumbProperties 中已经存在的任何内容(这样就避免了替换整个对象,只是单个属性的替换)。

    Feb

    4

    3.0 版本的项目升级到 3.1 的版本时,项目本身不需要进行修改(只是一个次要版本的升级)。但有一些简化的 API,提高开发人员的体验,特别是在处理字体样式和皮肤方面。

    用 starling.text.TextFormat 设置字体样式:

    从 Starling 2.0 开始,引入了 starling.text.TextFormat 类,它定义了所有类型文本使用的常见字体样式,包括位图字体和TTF / OTF字体。以前,要在 Feathers 文本渲染器上使用自定义字体样式,需要使用不同的类并设置不同的属性,具体取决于使用的文本渲染器。例如,TextBlockTextRenderer 具有类型为flash.text.engine.ElementFormat 的 elementFormat 属性,而 TextFieldTextRenderer 具有类型为 flash.text.TextFormat 的 textFormat 属性。现在,所有文本渲染器都有统一的方式来支持 starling.text.TextFormat 类。

    事实上,现在的字体样式不需要直接设置在文本渲染器对象本身上,开发者可以直接在使用到文本组件的对象上直接设置就可以,比如 Label、Button 这些组件用到了文本渲染器,就可以直接对这些父组件设置字体样式,父组件会自动将设置好的字体样式传递给文本渲染器。以 Label 组件为例:

    var label:Label = new Label();
    label.text = "Hello World";
    label.fontStyles = new TextFormat( "_sans"20, 0xff0000 );
    this.addChild( label );

    就是如此简单。在绝大多数情况下,根本不需要通过文本渲染器工厂(text renderer factories)设置。

    如果想设置 Label 禁用时的字体样式,只需如下代码:

    label.disabledFontStyles = new TextFormat( "_sans"20, 0x999999 );

    现在含有文本渲染器的绝大多数组件都包含了 fontStyles、disabledFontStyles 属性。如果一个组件是可选择的(类似“开关”),也会包含 selectedFontStyles 属性。

    如果组件包含有更多的状态,如 Button 组件,还包含了 setFontStylesForState() 方法用于设置不同状态字体的样式,此方法可以传入一个状态名称和一个用于设置字体样式的 TextFormat  对象,如下代码可以设置更多的状态时字体样式:

    var button:Button = new Button();
    button.setFontStylesForState( ButtonState.DOWN, new TextFormat( "_sans"20, 0xffffff ) );
    button.setFontStylesForState( ButtonState.HOVER, new TextFormat( "_sans"20, 0xff9999 ) );

    样式属性与主题:

    在以前的 Feathers 版本中,单独的皮肤设置经常会与主题文件中的代码产生“冲突”。为了避免这种问题,过去可能需要通过使用 AddOnFunctionStyleProvider 类,设置组件的 styleProvider 属性为 null,等待组件的初始化,或者需要扩展主题,但有时候可能仅仅只是需要一些微小的调整,所以这些方法无论是哪一种,都会显示麻烦一点。

    从 Feathers 3.1 开始, 一些属性现在被定义为“样式属性”。如果在主题之外设置样式属性,不需要再担心会被主题替换掉,而且还会同时保留主题文件中其它的皮肤设置(其它样式不会受到影响)。例如,如果在自定义的主题文件之外设置按钮的字体样式,但保持主题的背景皮肤,可以很容易:

    var button:Button = new Button();
    button.label = "Click Me";
    //不会再被主题文件中替换
    button.fontStyles = new TextFormat( "_sans"20, 0xff0000 );
    this.addChild( button );

    如果想要知道 Button 类被单独分离出来的样式属性有哪些,可以查看 API 手册

    主题中的最小尺寸:

    如果在主题文件中设置了普通属性,那么依旧有可能与主题外的代码产生“冲突”。例如,不应该直接对主题中的组件本身设置 minWidth 和 minHeight 属性。这些属性不被视为“样式属性”,所以如果在主题外同时设置的话,就会产生冲突。

    //比如在主题内有如下代码
    private function setButtonStyles( button:Button ):void
    {
        button.defaultSkin = new ImageSkin( texture );
        button.minWidth = 40//在主题内最好不要对组件本身设置这种普通属性
    }

    取而代之的是应该设置组件的皮肤:

    //在主题内
    private function setButtonStyles( button:Button ):void
    {
        var skin:ImageSkin = new ImageSkin( texture );
        skin.minWidth = 40;//对组件的皮肤进行设置
        skin.minHeight = 20;
        button.defaultSkin = backgroundSkin;
    }

    如果组件没有显示的尺寸设置,组件就会用皮肤的尺寸用于测量步骤。所以如上代码在皮肤上设置尺寸,实际上跟在组件上设置尺寸基本上是一样的。

    如果有些组件不需要显示皮肤,可以使用一个全透明的背景皮肤,可以简单地传入一个starling.display.Quad,设 alpha 属性设置为 0:

    var backgroundSkin:Quad = new Quad( 4020 );
    backgroundSkin.alpha = 0;
    component.backgroundSkin = backgroundSkin;

    Starling 不会要求 GPU 渲染一个完全透明的显示对象,因此这个透明背景不会增加 GPU 绘制调用的次数,也不会影响 GPU 绘制的性能。但这个 Quad 的尺寸会被视为测量步骤中的最小尺寸。

    当一个显示对象没有 minWidth 与 minHeight 属性时(如上面的 Quad),它的普通 width 与 height 属性也会被当作最小值。如果一定需要有 minWidth 与 minHeight 的值比普通的 width 与 height 属性值还要小,可以考虑使用 ImageSkin。

    Feb

    3

    升级指南:重复的常量移动到共享类:

    在以往旧的 Feathers 版本中,存在大量的重复常量。例如,可以在Button、DefaultListItemRenderer、HorizontalLayout 和 TiledRowsLayout 类(以及其他地方)上找到 HORIZONTAL_ALIGN_LEFT。在 Feathers 3.0 中,现在可以使用一个共享的 HorizontalAlign.LEFT 常量,换句话说,只要在一个类中使用了 HorizontalAlign.LEFT 常量,在后续其它的类中如果也同样需要这个常量就可以很容易找到它了。

    其它一些重复的常量也差不多都被合并处理了。以下这些类具有共享常量:

    feathers.controls.AutoSizeMode
    feathers.controls.ButtonState
    feathers.controls.DecelerationRate
    feathers.controls.ScrollBarDisplayMode
    feathers.controls.ScrollInteractionMode
    feathers.controls.ScrollPolicy
    feathers.controls.TextInputState
    feathers.layout.Direction
    feathers.layout.HorizontalAlign
    feathers.layout.RelativePosition
    feathers.layout.VerticalAlign

    有关弃用的常量对应到新的共享常量的详细信息,请参阅《附录:已弃用的API列表》。

    使用原先重复的常量不再被推荐的,虽然在短时间内为了兼容性还可以继续使用,但将来某些个版本中是一定会被删除的。如果旧项目中大量的用到了这些常量,需要快速的替换升级,可以参考《附录:查找和替换正则表达式》。

    Feb

    3

    升级指南:使用 Feathers 组件进行多分辨率开发:

    Feathers 3.0 完全支持 Starling 多分辨率开发中描述的 Starling 的 contentScaleFactor 系统。Feathers 甚至还提供了一些技巧,使其很容易扩展到任何移动设备的屏幕,同时保持其原生长宽比。

    屏幕像素密度缩放因子管理器(ScreenDensityScaleFactorManager):

    ScreenDensityScaleFactorManager 类提供了一种方便的方式,用来自动计算恰当的 contentScaleFactor 值,同时保持移动设备屏幕的宽高比(这是受到 Android 系统的启发,同时考虑了屏幕的像素密度和分辨率尺寸)。

    下面的代码演示了 ScreenDensityScaleFactorManager 的使用方法:

    public class Startup extends Sprite
    {
        private var mStarling:Starling;
        private var mScaler:ScreenDensityScaleFactorManager;

        public function Startup()
        {
            mStarling = new Starling( Game, stage );
            mScaler = new ScreenDensityScaleFactorManager( mStarling );
            mStarling.start();
        }
    }

    开发者不需要设置 Starling 的 viewPort,也不需要设置 Starling 舞台的 stageHeight 与 stageWidth 属性。ScreenDensityScaleFactorManager 类会自动为开发者处理这些(既使设备旋转了方向)。

    在使用 Feathers 库进行开发的时候,ScreenDensityScaleFactorManager 的使用是可选的。如果想按 Starling WIKI 手册中 《Multi-Resolution Development》介绍的那样手动设置 viewPort 与  舞台的 stageHeight 与 stageWidth 属性也同样可以。

    示例主题的变化:

    Feathers UI 库提供的示例主题已被修改成为允许 Starling 通过 contentScaleFactor 自动缩放资源,在示例主题中的缩放因子为 2。示例主题的缩放因子不再是通过屏幕像素密度计算出来的,无论是像素尺寸或字体大小,都使用相同的缩放因子。

    如果示例主题的子类定义了一个 scale9Grid 矩形,值可能需要经过缩放计算才能适合在 Feathers 3.0 中使用。在以前的 Feathers 版本中,示例主题的纹理缩放因子都是 1,然后手动计算需要缩放的倍数。由于现在的缩放因子变成了2,因为旧的 scale9Grid 相关的值应该除以2。需要注意的是,如果原先是个奇,向上取整,皮肤 可能需要扩展额外的像素以取得偶数值。

    Feb

    3

    升级指南:返回类型 API 更改:

    Drawers 现在要求 content 与 drawers 都为 Feathers 组件,在以前的旧版本中可以使用 starling.display.Sprite 对象,新版中不再被允许了,如果想用一个对象代替以往通用的 Starling  Sprite 对象,可以考虑使用 LayoutGroup 作为替代品。

    INativeFocusOwner 实现类的 nativeFocus 属性现在返回一个 Object  对象,以允许像 flash.text.StageText 这样的对象接收焦点。以前的旧版本中返回的是 flash.display.InteractiveObject 对象。

    Feb

    3

    升级指南:关于尺寸测量—— 用 saveMeasurements() 方法代替 setSizeInternal() 方法:

    自定义组件时应该使用新的 saveMeasurements() 方法代替旧的 setSizeInternal() 方法,旧方法已被视为弃用的(不再被推荐)。

    新方法除了有更直观的名字外,saveMeasurements() 允许组件动态设置最小尺寸(最小宽度和高度):

    this.saveMeasurements(newWidth, newHeight, newMinWidth, newMinHeight);

    如果想和旧版本的行为相似,可以将最小宽与高设为 0:

    this.saveMeasurements(newWidth, newHeight, 00);

    还可以将最小尺寸与常规尺寸相同:

    this.saveMeasurements(newWidth, newHeight, newWidth, newHeight);

    如果没有为 Feathers 组件明确的指定最小尺寸,Feathers 会自动计算出一个最小尺寸。

    关于 saveMeasurements() 更多的其它备注资料查看:Feathers3 “组件生命周期”一些备注》。

    Feb

    3

    升级指南:皮肤方面的更改(4)—— 删除了 StandardIcons.listDrillDownAccessoryTexture:

    在以前的版本中,此静态属性用于返回项渲染器 accessorySourceFunction 中的特定图标(冒似下拉图标)。在 Feathers 3.0 中,用户应将 DefaultListItemRenderer.ALTERNATE_STYLE_NAME_DRILL_DOWN 常量添加到项渲染器的 styleNameList 中,主题会自动检测此样式名称,并为项渲染器传入一个特定的图标。DefaultGroupedListItemRenderer  也同样定义了一个ALTERNATE_STYLE_NAME_DRILL_DOWN 常量。

    如果列表中的一些项渲染器不需要特定的图标,使用 setItemRendererFactoryWithID() 和 factoryIDFunction 为 List 或 GroupedList 传入多个项渲染器

    list.itemRendererFactory = function():IListItemRenderer
    {
        var itemRenderer:DefaultListItemRenderer = new DefaultListItemRenderer();
        itemRenderer.styleNameList.add( DefaultListItemRenderer.ALTERNATE_STYLE_NAME_DRILL_DOWN );
        return itemRenderer;
    };

    如果所有的项都有特定的图标,则可以改用 customItemRendererStyleName 属性:

    list.customItemRendererStyleName = DefaultListItemRenderer.ALTERNATE_STYLE_NAME_DRILL_DOWN;