Flex 3框架中容器的边框,背景色和背景图片是如何实现的?
作者:Admin 日期:2008-09-17
以下分析都从flex 3源代码推出,不一定正确!希望能和有兴趣的朋友一起探讨。
Flex 3 框架中,容器的边框,背景色和背景图片是由容器的borderSkin 类(为了叙述方便,假设我们为容器定义了一个样式borderSkin: ClassReference("mx.skins.halo.HaloBorder"))来负责的,容器类如果检测到需要边框,背景色或者背景图片,容器会在自己内部建立一个HaloBorder类型的对象(
程序代码)border,在渲染过程中border负责建立边框,背景色或者背景图片。
原理如下:
每个容器的createChildren()方法中会调用createBorder()方法来判断是否需要建立border,只有符合下面两个条件我们的容器才会建立边框:
[1]容器没有边框(border == null);
[2]我们定义了容器的borderSkin样式 ,并且该样式类不是 mx.skins.halo::HaloBorder 或者 我们定义了容器的borderSkin样式 ,并且该样式类是 mx.skins.halo::HaloBorder那么
[2.1]borderStyle 样式不是 none 或者 borderStyle 样式是 none 并且定义了 mouseShield 样式 或者 borderStyle 样式是 none 并且没有定义 mouseShield 样式 那么
[2.1.1]如果定义了 backgroundColor 并且 backgroundColor != "" 或者 定义了backgroundImage 并且 backgroundImage != ""
flex3 框架中 mx.skin::RectangularBorder 类支持backgroundImage, backgroundSize,backgroundAttachment 样式。mx.skin::HaloBorder 类实现了 backgroundColor 和 边框的绘制。
类的继承链如下:HaloBorder - RectangularBorder - Border - ProgrammaticSkin - FlexShape - Shape - DisplayObject - EventDispatcher - Object
设置了 borderSkin: ClassReference("mx.skins.halo.HaloBorder")的容器,最底层是背景色和边框(因为背景色和边框用的是graphics绘制的),背景色上面是背景图片,背景图片上面是容器的子孙。
此文禁止转载,但是您可以以超级链接的方式链接到这篇文章。
附录 方便我自己查阅而放在这里
默认主题(framework.swc 中包含的 default.css文件)中有关边框,背景色和背景图片的定义
程序代码
global
{
backgroundAlpha: 1.0; /* this runs the opacity of nearly every square piece of the components */
/* backgroundDisabledColor: #DDDDDD; */
backgroundSize: "auto";
bevel: true;
borderAlpha: 1.0;
borderCapColor: #919999;
borderColor: #B7BABC;
borderSides: "left top right bottom";
borderSkin: ClassReference("mx.skins.halo.HaloBorder");
borderStyle: "inset";
borderThickness: 1;
...........
}
Container
{
borderStyle: "none";
}
mx.core::Container 类中的和本文有关的一些定义:
程序代码
/**
* @private
* Create components that are children of this Container.
*/
override protected function createChildren():void
{
super.createChildren();
// Create the border/background object.
createBorder();
// To save ourselves an extra layout pass, check to see
// if the scrollbars will definitely be needed.
// If so, create them now.
createOrDestroyScrollbars(
horizontalScrollPolicy == ScrollPolicy.ON,
verticalScrollPolicy == ScrollPolicy.ON,
horizontalScrollPolicy == ScrollPolicy.ON ||
verticalScrollPolicy == ScrollPolicy.ON);
// Determine the child-creation policy (ContainerCreationPolicy.AUTO,
// ContainerCreationPolicy.ALL, or ContainerCreationPolicy.NONE).
// If the author has specified a policy, use it.
// Otherwise, use the parent's policy.
// This must be set before createChildren() gets called.
if (creationPolicy != null)
{
actualCreationPolicy = creationPolicy;
}
else if (parent is Container)
{
if (Container(parent).actualCreationPolicy ==
ContainerCreationPolicy.QUEUED)
{
actualCreationPolicy = ContainerCreationPolicy.AUTO;
}
else
{
actualCreationPolicy = Container(parent).actualCreationPolicy;
}
}
// It is ok for actualCreationPolicy to be null. Popups require it.
if (actualCreationPolicy == ContainerCreationPolicy.NONE)
{
actualCreationPolicy = ContainerCreationPolicy.AUTO;
}
else if (actualCreationPolicy == ContainerCreationPolicy.QUEUED)
{
var mainApp:Application = parentApplication ?
Application(parentApplication) :
Application(Application.application);
mainApp.addToCreationQueue(this, creationIndex, null, this);
}
else if (recursionFlag)
{
// Create whatever children are appropriate. If any were
// previously created, they don't get re-created.
createComponentsFromDescriptors();
}
// If autoLayout is initially false, we still want to do
// measurement once (even if we don't have any children)
if (autoLayout == false)
forceLayout = true;
// weak references
UIComponentGlobals.layoutManager.addEventListener(
FlexEvent.Update_COMPLETE, layoutCompleteHandler, false, 0, true);
}
/**
* Creates the container's border skin
* if it is needed and does not already exist.
*/
protected function createBorder():void
{
if (!border && isBorderNeeded())
{
var borderClass:Class = getStyle("borderSkin");
if (borderClass != null)
{
border = new borderClass();
border.name = "border";
if (border is IUIComponent)
IUIComponent(border).enabled = enabled;
if (border is ISimpleStyleClient)
ISimpleStyleClient(border).styleName = this;
// Add the border behind all the children.
rawChildren.addChildAt(DisplayObject(border), 0);
invalidateDisplayList();
}
}
}
/**
* @private
*/
private function isBorderNeeded():Boolean
{
//trace("isBorderNeeded",this,"ms",getStyle("mouseShield"),"borderStyle",getStyle("borderStyle"));
// If the borderSkin is a custom class, always assume the border is needed.
var c:Class = getStyle("borderSkin");
// Lookup the HaloBorder class by name to avoid a linkage dependency.
// Note: this code assumes HaloBorder is the default border skin. If this is changed
// in defaults.css, it must also be changed here.
try
{
if (c != getDefinitionByName("mx.skins.halo::HaloBorder"))
return true;
}
catch(e:Error)
{
return true;
}
var v:Object = getStyle("borderStyle");
if (v)
{
// If borderStyle is "none", then only create a border if the mouseShield style is true
// (meaning that there is a mouse event listener on this view). We don't create a border
// if our parent's mouseShieldChildren style is true.
if ((v != "none") || (v == "none" && getStyle("mouseShield")))
{
return true;
}
}
v = getStyle("backgroundColor");
if (v !== null && v !== "")
return true;
v = getStyle("backgroundImage");
return v != null && v != "";
}
override public function styleChanged(styleProp:String):void
{
var allStyles:Boolean = styleProp == null || styleProp == "styleName";
// Check to see if this is one of the style properties that is known
// to affect page layout.
if (allStyles || StyleManager.isSizeInvalidatingStyle(styleProp))
{
// Some styles, such as horizontalAlign and verticalAlign,
// affect the layout of this object's children without changing the
// view's size. This function forces the view to be remeasured
// and layed out.
invalidateDisplayList();
}
// Replace the borderSkin
if (allStyles || styleProp == "borderSkin")
{
if (border)
{
rawChildren.removeChild(DisplayObject(border));
border = null;
createBorder();
}
}
// Create a border object, if none previously existed and
// one is needed now.
if (allStyles ||
styleProp == "borderStyle" ||
styleProp == "backgroundColor" ||
styleProp == "backgroundImage" ||
styleProp == "mouseShield" ||
styleProp == "mouseShieldChildren")
{
createBorder();
}
super.styleChanged(styleProp);
// Check to see if this is one of the style properties that is known.
// to affect page layout.
if (allStyles ||
StyleManager.isSizeInvalidatingStyle(styleProp))
{
invalidateViewMetricsAndPadding();
}
if (allStyles || styleProp == "horizontalScrollBarStyleName")
{
if (horizontalScrollBar && horizontalScrollBar is ISimpleStyleClient)
{
var horizontalScrollBarStyleName:String =
getStyle("horizontalScrollBarStyleName");
ISimpleStyleClient(horizontalScrollBar).styleName =
horizontalScrollBarStyleName;
}
}
if (allStyles || styleProp == "verticalScrollBarStyleName")
{
if (verticalScrollBar && verticalScrollBar is ISimpleStyleClient)
{
var verticalScrollBarStyleName:String =
getStyle("verticalScrollBarStyleName");
ISimpleStyleClient(verticalScrollBar).styleName =
verticalScrollBarStyleName;
}
}
}
Flex 3 框架中,容器的边框,背景色和背景图片是由容器的borderSkin 类(为了叙述方便,假设我们为容器定义了一个样式borderSkin: ClassReference("mx.skins.halo.HaloBorder"))来负责的,容器类如果检测到需要边框,背景色或者背景图片,容器会在自己内部建立一个HaloBorder类型的对象(
程序代码border = new mx.skins.halo.HaloBorder();
// Add the border behind all the children.
rawChildren.addChildAt(DisplayObject(border), 0);
// Add the border behind all the children.
rawChildren.addChildAt(DisplayObject(border), 0);
原理如下:
每个容器的createChildren()方法中会调用createBorder()方法来判断是否需要建立border,只有符合下面两个条件我们的容器才会建立边框:
[1]容器没有边框(border == null);
[2]我们定义了容器的borderSkin样式 ,并且该样式类不是 mx.skins.halo::HaloBorder 或者 我们定义了容器的borderSkin样式 ,并且该样式类是 mx.skins.halo::HaloBorder那么
[2.1]borderStyle 样式不是 none 或者 borderStyle 样式是 none 并且定义了 mouseShield 样式 或者 borderStyle 样式是 none 并且没有定义 mouseShield 样式 那么
[2.1.1]如果定义了 backgroundColor 并且 backgroundColor != "" 或者 定义了backgroundImage 并且 backgroundImage != ""
flex3 框架中 mx.skin::RectangularBorder 类支持backgroundImage, backgroundSize,backgroundAttachment 样式。mx.skin::HaloBorder 类实现了 backgroundColor 和 边框的绘制。
类的继承链如下:HaloBorder - RectangularBorder - Border - ProgrammaticSkin - FlexShape - Shape - DisplayObject - EventDispatcher - Object
设置了 borderSkin: ClassReference("mx.skins.halo.HaloBorder")的容器,最底层是背景色和边框(因为背景色和边框用的是graphics绘制的),背景色上面是背景图片,背景图片上面是容器的子孙。
此文禁止转载,但是您可以以超级链接的方式链接到这篇文章。
附录 方便我自己查阅而放在这里
默认主题(framework.swc 中包含的 default.css文件)中有关边框,背景色和背景图片的定义
程序代码global
{
backgroundAlpha: 1.0; /* this runs the opacity of nearly every square piece of the components */
/* backgroundDisabledColor: #DDDDDD; */
backgroundSize: "auto";
bevel: true;
borderAlpha: 1.0;
borderCapColor: #919999;
borderColor: #B7BABC;
borderSides: "left top right bottom";
borderSkin: ClassReference("mx.skins.halo.HaloBorder");
borderStyle: "inset";
borderThickness: 1;
...........
}
Container
{
borderStyle: "none";
}
mx.core::Container 类中的和本文有关的一些定义:
程序代码/**
* @private
* Create components that are children of this Container.
*/
override protected function createChildren():void
{
super.createChildren();
// Create the border/background object.
createBorder();
// To save ourselves an extra layout pass, check to see
// if the scrollbars will definitely be needed.
// If so, create them now.
createOrDestroyScrollbars(
horizontalScrollPolicy == ScrollPolicy.ON,
verticalScrollPolicy == ScrollPolicy.ON,
horizontalScrollPolicy == ScrollPolicy.ON ||
verticalScrollPolicy == ScrollPolicy.ON);
// Determine the child-creation policy (ContainerCreationPolicy.AUTO,
// ContainerCreationPolicy.ALL, or ContainerCreationPolicy.NONE).
// If the author has specified a policy, use it.
// Otherwise, use the parent's policy.
// This must be set before createChildren() gets called.
if (creationPolicy != null)
{
actualCreationPolicy = creationPolicy;
}
else if (parent is Container)
{
if (Container(parent).actualCreationPolicy ==
ContainerCreationPolicy.QUEUED)
{
actualCreationPolicy = ContainerCreationPolicy.AUTO;
}
else
{
actualCreationPolicy = Container(parent).actualCreationPolicy;
}
}
// It is ok for actualCreationPolicy to be null. Popups require it.
if (actualCreationPolicy == ContainerCreationPolicy.NONE)
{
actualCreationPolicy = ContainerCreationPolicy.AUTO;
}
else if (actualCreationPolicy == ContainerCreationPolicy.QUEUED)
{
var mainApp:Application = parentApplication ?
Application(parentApplication) :
Application(Application.application);
mainApp.addToCreationQueue(this, creationIndex, null, this);
}
else if (recursionFlag)
{
// Create whatever children are appropriate. If any were
// previously created, they don't get re-created.
createComponentsFromDescriptors();
}
// If autoLayout is initially false, we still want to do
// measurement once (even if we don't have any children)
if (autoLayout == false)
forceLayout = true;
// weak references
UIComponentGlobals.layoutManager.addEventListener(
FlexEvent.Update_COMPLETE, layoutCompleteHandler, false, 0, true);
}
/**
* Creates the container's border skin
* if it is needed and does not already exist.
*/
protected function createBorder():void
{
if (!border && isBorderNeeded())
{
var borderClass:Class = getStyle("borderSkin");
if (borderClass != null)
{
border = new borderClass();
border.name = "border";
if (border is IUIComponent)
IUIComponent(border).enabled = enabled;
if (border is ISimpleStyleClient)
ISimpleStyleClient(border).styleName = this;
// Add the border behind all the children.
rawChildren.addChildAt(DisplayObject(border), 0);
invalidateDisplayList();
}
}
}
/**
* @private
*/
private function isBorderNeeded():Boolean
{
//trace("isBorderNeeded",this,"ms",getStyle("mouseShield"),"borderStyle",getStyle("borderStyle"));
// If the borderSkin is a custom class, always assume the border is needed.
var c:Class = getStyle("borderSkin");
// Lookup the HaloBorder class by name to avoid a linkage dependency.
// Note: this code assumes HaloBorder is the default border skin. If this is changed
// in defaults.css, it must also be changed here.
try
{
if (c != getDefinitionByName("mx.skins.halo::HaloBorder"))
return true;
}
catch(e:Error)
{
return true;
}
var v:Object = getStyle("borderStyle");
if (v)
{
// If borderStyle is "none", then only create a border if the mouseShield style is true
// (meaning that there is a mouse event listener on this view). We don't create a border
// if our parent's mouseShieldChildren style is true.
if ((v != "none") || (v == "none" && getStyle("mouseShield")))
{
return true;
}
}
v = getStyle("backgroundColor");
if (v !== null && v !== "")
return true;
v = getStyle("backgroundImage");
return v != null && v != "";
}
override public function styleChanged(styleProp:String):void
{
var allStyles:Boolean = styleProp == null || styleProp == "styleName";
// Check to see if this is one of the style properties that is known
// to affect page layout.
if (allStyles || StyleManager.isSizeInvalidatingStyle(styleProp))
{
// Some styles, such as horizontalAlign and verticalAlign,
// affect the layout of this object's children without changing the
// view's size. This function forces the view to be remeasured
// and layed out.
invalidateDisplayList();
}
// Replace the borderSkin
if (allStyles || styleProp == "borderSkin")
{
if (border)
{
rawChildren.removeChild(DisplayObject(border));
border = null;
createBorder();
}
}
// Create a border object, if none previously existed and
// one is needed now.
if (allStyles ||
styleProp == "borderStyle" ||
styleProp == "backgroundColor" ||
styleProp == "backgroundImage" ||
styleProp == "mouseShield" ||
styleProp == "mouseShieldChildren")
{
createBorder();
}
super.styleChanged(styleProp);
// Check to see if this is one of the style properties that is known.
// to affect page layout.
if (allStyles ||
StyleManager.isSizeInvalidatingStyle(styleProp))
{
invalidateViewMetricsAndPadding();
}
if (allStyles || styleProp == "horizontalScrollBarStyleName")
{
if (horizontalScrollBar && horizontalScrollBar is ISimpleStyleClient)
{
var horizontalScrollBarStyleName:String =
getStyle("horizontalScrollBarStyleName");
ISimpleStyleClient(horizontalScrollBar).styleName =
horizontalScrollBarStyleName;
}
}
if (allStyles || styleProp == "verticalScrollBarStyleName")
{
if (verticalScrollBar && verticalScrollBar is ISimpleStyleClient)
{
var verticalScrollBarStyleName:String =
getStyle("verticalScrollBarStyleName");
ISimpleStyleClient(verticalScrollBar).styleName =
verticalScrollBarStyleName;
}
}
}
评论: 2 | 引用: 0 | 查看次数: 7724
好文
flex最终输出的毕竟不是HTML,
所以负责的紧啊,
经常被控件的样式折磨
flex最终输出的毕竟不是HTML,
所以负责的紧啊,
经常被控件的样式折磨
发表评论
上一篇
下一篇

文章来自:
Tags:
回复
panel里加了borderskin的属性之后,panel标题的高度就丢失了,这个问题该如何解决?求教!谢谢!QQ:309925294