- 论坛徽章:
- 0
|
1.概述 本文介绍了Gumbo的皮肤框架原理。不象MX的skinning仅是一个简单的图形操作,Gumbo的skin是一个综合的、可以包含多个元素(比如图形元素,文本、图片、转换等),主要亮点如下: . 所有可视特征,包括layou都可以在skin中控制。 . 所有的skin保持简单、一致,Button的皮肤与List Item的皮肤可以是一样的 . 通过skin parts可以进行皮肤的组合 . 通过配置文件描述可以容易创建和控制
2.使用场景 最常用场景: 有一个控件,比如Button,不通过任何ActionScript代码,只用创建一个新的ButtonSkin ,因为skin 文件是MXML,设计人员很容易进行设计皮肤。
其它场景: 开发人员创建一个自定义组件,但可以自定义皮肤。通过继承SkinnableComponent即可。 设计人员通过修改CSS就可以改变应用程序的皮肤。
3.详细描述 每个组件包含四个概念:model, skin, controller和view-specific logic(可视化描述逻辑)。
model 包含组件的属性和业务逻辑。比如Range model的属性有:minimumValue, maximumValue, stepSize等。方法有:画线。model 不能包含任何可视化或行为信息。
skin 定义了组件的可视化元素。
controller 是skin和model的接口。它具有几个关键功能: . 定义组件行为,比如:Button控制器具有mouse事件处理逻辑。 . 定义组件的可视化状态 . 定义组件的组成部分。比如一个scrollbar控制器具有4部分:up arrow, down arrow, thumb, 和track。
view-specific logic描述skin中不同组件的位置和大小,比如HScrollBar 和 VScrollBar具有不同的可视描述逻辑,决定thumb的位置。为了通知scrollbar,必须重载其逻辑。
skinnable componen在编程和运行期间,其皮肤都可以改变。
4.组装 . model 和 controller可以用ActionScript编写。 . model和controller有时并不容易区分,尤其当model是UI组件时。 . skin以MXML格式编写 . view-specific logic可以写在skin文件中,但是绝大多数时候,logic应该放到组件中去,或者是组件的一个子类,比如ScrollBarBase->HScrollBar 或 ScrollBarBase->VScrollBar. . 对于skinnable组件, 通过 CSS与skins关联。
其关系如下
 左边的绿箭头表示继承关系,红箭头表示CSS转换。
5.在skins中编码 VS 在组件中编码 通常,应该把所有的可视逻辑放在skin中,尤其是想做成可定制的。但是,这很难清楚的划分。 view-specific logic 可以放在skin中,也可以放在组件中。 一般来讲,在多个skin中使用的代码应放在组件中, 特定的皮肤描述应放在skin中。
比如,scrollbar拥有position和size属性,因为对于所有的scrollbars 都需要这二个属性。因为多个skin利用view-specific logic去定位scrollbar,因此就有了HScrollBar 子类来完成这个需求。
如果开发人员只是创建了一次性使用的组件,可以把view-specific logic放在skin文件中,而不是组件的子类中。
6.状态 一些组件,象Button,可以在skin中使用状态。组件通过SkinState 元数据定义这些状态,并在skin中定义这些状态。
在组件中
- /**
-
* Up State of the Button
-
*/
-
[SkinState("up")]
-
-
/**
-
* Over State of the Button
-
*/
-
[SkinState("over")]
-
-
/**
-
* Down State of the Button
-
*/
-
[SkinState("down")]
-
-
/**
-
* Disabled State of the Button
-
*/
-
[SkinState("disabled")]
-
-
public class Button extends SkinnableComponent {
-
...
-
}
在skin中
- <s:Skin xmlns:fx="http://ns.adobe.com/mxml/2009" xmlns:s="library://ns.adobe.com/flex/spark">
-
<s:states>
-
<s:State name="up" />
-
<s:State name="over" />
-
<s:State name="down" />
-
<s:State name="disabled" />
-
</s:states>
-
-
...
-
</s:Skin>
在组件中的controller 代码决定skin的状态,通过skin中的currentState属性定义当前状态。
SkinState 元数据是一种组件在skin中定义状态的方式。如果skin没有定义需要的状态,编译器将抛出错误。
子类可以从父类中继承SkinState,比如: Button声明skin states : "up", "over", "down", "disabled"。 ToggleButton 声明skin states : "upAndSelected", "overAndSelected", "downAndSelected", "disabledAndSelected" ,并继承了Button所有的skin状态。
一个skin的状态不必与组件的状态相同。button的currentState 不必与ButtonSkin的currentState 属性一致。button 影响skin的状态。用户通过设置组件的属性影响skin的状态,比如设置toggleButton selected=true/false。
开发人员可以使用invalidateSkinState() 和getCurrentSkinState() 改变skin的状态, invalidateSkinState() 验证skin状态。
例如 (Button.as):
- package spark.components
-
{
-
-
/**
-
* Up State of the Button
-
*/
-
[SkinState("up")]
-
-
/**
-
* Over State of the Button
-
*/
-
[SkinState("over")]
-
-
/**
-
* Down State of the Button
-
*/
-
[SkinState("down")]
-
-
/**
-
* Disabled State of the Button
-
*/
-
[SkinState("disabled")]
-
-
public class Button extends SkinnableComponent implements IFocusManagerComponent
-
{
-
-
...
-
-
/**
-
* @return Returns true when the mouse cursor is over the button.
-
*/
-
public function get isHoveredOver():Boolean
-
{
-
return flags.isSet(isHoveredOverFlag);
-
}
-
-
/**
-
* Sets the flag indicating whether the mouse cursor
-
* is over the button.
-
*/
-
protected function setHoveredOver(value:Boolean):void
-
{
-
if (!flags.update(isHoveredOverFlag, value))
-
return;
-
-
invalidateSkinState();
-
}
-
-
...
-
-
// GetState returns a string representation of the component's state as
-
// a combination of some of its public properties
-
protected override function getUpdatedSkinState():String
-
{
-
if (!isEnabled)
-
return "disabled";
-
-
if (isDown())
-
return "down";
-
-
if (isHoveredOver || isMouseCaptured )
-
return "over";
-
-
return "up";
-
}
-
-
...
-
-
//--------------------------------------------------------------------------
-
//
-
// Event handling
-
//
-
//--------------------------------------------------------------------------
-
-
protected function mouseEventHandler(event:Event):void
-
{
-
var mouseEvent:MouseEvent = event as MouseEvent;
-
switch (event.type)
-
{
-
case MouseEvent.ROLL_OVER:
-
{
-
// if the user rolls over while holding the mouse button
-
if (mouseEvent.buttonDown && !isMouseCaptured)
-
return;
-
setHoveredOver(true);
-
break;
-
}
-
-
case MouseEvent.ROLL_OUT:
-
{
-
setHoveredOver(false);
-
break;
-
}
-
-
...
-
}
-
}
-
}
-
-
}
待续
参考文献 1.Spark Skinning (including SkinnableComponent) - Functional and Design Specification. http://opensource.adobe.com/wiki/display/flexsdk/Spark+Skinning 2.
|
|