Flex样式工作原理分析 Part Two(完结)

以下分析都从flex3源代码推出,不一定正确!希望能和有兴趣的朋友一起探讨。

Flex样式工作原理分析 Part One中,我们分析了组件是如何获得样式信息的,下面来谈一下设置样式是如何工作的。

每当组件需要重新设置自己的样式时(比如说调用了setStyle()方法或者设置了styleName属性),组件的styleChanged(styleProp:String)方法就会被调用,然后我们在styleChanged(styleProp:String)方法体里面根据参数styleProp的值的不同来对组件的样式做出相应的处理。那么什么时候组件的styleChanged(styleProp:String)方法会触发呢?下面介绍如下:

1,setStyle()方法
当我们调用setStyle()方法的时候,首先会调用该组件的styleChanged(styleProp)然后判断改变的样式是否是可继承样式,如果是,则调用该组件的所有子孙的styleChanged(styleProp)方法。比如:
程序代码 程序代码
<mx:Canvas id="myCanvas">
    <mx:Vbox id="box" x="0" y="10" width="200">
        <mx:Label id="text1" text="@Resource(key='name', bundle='test')" color="#ff0000"/>
        <mx:Label id="text2" text="@Resource(key='age', bundle='test')" styleName="ageLabel"/>
        <mx:Label id="text3" text="@Resource(key='sex', bundle='test')"/>
        <mx:Label id="text4" text="{resourceManager.getString('test', 'sex')}"/>
    </mx:Vbox>
    <mx:Button id="myBtn" x="27" y="100" label="change" click="changeHandler(event)"/>    
</mx:Canvas>  

当我们调用 myCanvas.setStyle("color", 0xff0000)的时候,首先会重新设置该组件的样式缓存(CSS style cache),
这样调用myCanvas.getStyle("color")时就能得到值0xff0000。然后调用myCanvas.styleChanged("color"); 因为
color是可继承样式,所以会接着调用box.styleChanged("color"),text1.styleChanged("color"),text2.styleChanged("color"),text3.styleChanged("color"),text4.styleChanged("color"),myBtn.styleChanged("color");
当我们调用 myCanvas.setStyle("backgroundColor", 0xff0000)的时候,首先调用myCanvas.styleChanged("backgroundColor")因为backgroundColor不是可继承样式,所以myCanvas的子孙的styleChanged(styleProp)方法不会被调用。

2. addChild(chlid)的时候
当我们使用addChild(chlid)时,首先会重新设置该组件和该组件的子孙的样式缓存,然后调用chlid.styleChanged(null) 和chlid的子孙的styleChanged(null)方法。

3, 设置 styleName
当我们给一个组件(比如实例名是child)设置styleName属性时,首先会重新设置该组件和该组件的子孙的样式缓存,然后调用chlid.styleChanged("styleName")和chlid的子孙的styleChanged("styleName")方法。

4, 运行时载入样式表单
运行时载入样式表单我们通常会使用StyleManager.loadStyleDeclarations(url:String, update:Boolean = true, trustContent:Boolean = false, applicationDomain:ApplicationDomain = null, securityDomain:SecurityDomain = null)方法。当把参数update设置为true时表示样式表单载入完成后马上更新样式。其原理是:样式表单载入完成后程序中的所有组件会重新设置组件的样式缓存,并调用组件的styleChanged(null)方法。

当我们建立一个ActionScript自定义组件(ActionScript Custom Components),并且该组件支持自定义样式的时候,我们的组件类里面必须要有一个
程序代码 程序代码
override public function styleChanged(styleProp:String):void
{
    // 方法体
}
方法。为什么呢?应为如果没有这个方法,你怎么来检测你的样式的改变呢?
通过我上面的分析,相信你一定能设计出一个出色的适应Flex框架的支持自定义样式的组件。关于“自定义组件支持自定义样式”你可以参考Flex帮助文档里面的 ActionScript Custom Components / Custom Style Properties 一节。

此文禁止转载,但是您可以以超级链接的方式链接到这篇文章。

下面是 UIComponent 组件里面的styleChanged(styleProp:String):void方法的定义,和本文无关,只是方便我自己查阅而放在这里。
程序代码 程序代码
/**
     *  Detects changes to style properties. When any style property is set,
     *  Flex calls the <code>styleChanged()</code> method,
     *  passing to it the name of the style being set.
     *
     *  <p>This is an advanced method that you might override
     *  when creating a subclass of UIComponent. When you create a custom component,
     *  you can override the <code>styleChanged()</code> method
     *  to check the style name passed to it, and handle the change accordingly.
     *  This lets you override the default behavior of an existing style,
     *  or add your own custom style properties.</p>
     *
     *  <p>If you handle the style property, your override of
     *  the <code>styleChanged()</code> method should call the
     *  <code>invalidateDisplayList()</code> method to cause Flex to execute
     *  the component's <code>updateDisplayList()</code> method at the next screen update.</p>
     *
     *  @param styleProp The name of the style property, or null if all styles for this
     *  component have changed.
     */
    public function styleChanged(styleProp:String):void
    {
        // If font changed, then invalidateProperties so
        // we can re-create the text field in commitProperties
        if (this is IFontContextComponent && hasFontContextChanged())
            invalidateProperties();
        
        // Check to see if this is one of the style properties
        // that is known to affect layout.

        If (!styleProp ||
            styleProp == "styleName" ||
            StyleManager.isSizeInvalidatingStyle(styleProp))
        {
            // This style property change may affect the layout of this
            // object. Signal the LayoutManager to re-measure the object.
            invalidateSize();
        }

        if (!styleProp ||
            styleProp == "styleName" ||
            styleProp == "themeColor")
        {
            initThemeColor();
        }
        
        invalidateDisplayList();

        if (parent is Iinvalidating)
        {
            if (StyleManager.isParentSizeInvalidatingStyle(styleProp))
                Iinvalidating(parent).invalidateSize();

            if (StyleManager.isParentDisplayListInvalidatingStyle(styleProp))
                Iinvalidating(parent).invalidateDisplayList();
        }
    }


[本日志由 Admin 于 2008-09-08 03:19 PM 编辑]
文章来自: 本站原创
引用通告: 查看所有引用 | 我要引用此文章
Tags:
评论: 0 | 引用: 0 | 查看次数: 3118
发表评论
昵 称:
密 码: 游客发言不需要密码.
内 容:
验证码: 验证码
选 项:
字数限制 1000 字 | UBB代码 开启 | [img]标签 关闭